home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Belgian Amiga Club - ADF Collection
/
BS1 part 60.zip
/
BS1 part 60
/
LSD 32.adf
/
AmigaGfx6.pp
/
AmigaGfx6
Wrap
Text File
|
1990-09-07
|
221KB
|
6,268 lines
_________________________________________________________________________
/#########################################################################\
|#####...####..######..######......####...####..#####..##......##......###|
|####.....###..######..########..#####.....###...####..##..######..#######|
|###..###..##..######..########..####..###..##....###..##..######..#######|
|###..###..##..######..########..####..###..##..#...#..##..######......###|
|###.......##..######..########..####.......##..##.....##..######..#######|
|###..###..##..######..########..####..###..##..###....##..######..#######|
|###..###..##...#####...#######..####..###..##..####...##..######..#######|
|###..###..##......##......##......##..###..##..#####..##......##......###|
|#########################################################################|
|####################################################################{RB}#|
|=========================================================================|
| |
| ----> PRESENTS <---- |
| |
| AMIGA GRAPHICS INSIDE AND OUT - THE COMPLETE BOOK |
| |
| > PART 6 < |
| |
| Typed / Scanned / Edited By : RAZOR BLADE. |
| Additional Typing by : GLITCH ( + 8 pages by Asterix ! ). |
| Original Supplied by : VIPER |
| |
|-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-|
| CALL THE ALLIANCE WORLD HQ -> THE PLACE TO BE |
| UNKNOWN PLEASURES --> +44 (0) 823 322 891 --> SYSOP: BARBARIAN |
|_________________________________________________________________________|
-----------------------------------------------------------------------------
18.3 AnimObs and AnimComps
Displaying only "static" bobs isn't very exciting. Because of this, a
special animation system was created specifically for bobs. At the
beginning of this C language section, you learned one method of animation
called "color cycling" or color animation. We cycled, or scrolled, the colors
in the color registers. The contents of the preceding register were
exchanged for the contents of the current register, etc.
You also learned a second type of animation. When you moved your bobs and
vsprites they were also animated. You may be thinking that a
Commodore 64 is also able to do this. Although this is true, the Amiga is
also capable of animating bobs using the operating system software and
drawing a bob in different sequences without any commands.
The Amiga can recognise Animation Objects called AnimObs. We define
AnimObs with AnimationComponents, which are named AnimComps. The AnimComps
contain our defined bobs. For example, you could create the flight of a
seagull with different bob sequences. Then you could link these bobs with
the AnimComps and create an AnimOb.
The first step of this process is to create all your bobs as you usually do.
In addition to the flags, you must determine how the bob is written into
the bit-map (OVERLAY, SAVEBACK, etc.) and set the bobs
PAGE 479
-----------------------------------------------------------------------------
BOBISCOMP flag. This tells the animation software that your bob is an
animation component. You must also tell the system to which animation
component your bob belongs. To do this, set the pointer Bob.BobComp for
the corresponding Animcomp structure. Each animated bob requires its
own AnimComp structure.
To link the AnimComps together, use the pointers AnimComp.NextComp and
AnimComp.PrevComp. These two pointers point to the previous and next
AnimComps. Be careful because When you create a loop here it should
point only to a single AnimComp. Also, for all other AnimComps, you must
set these pointers to zero. If you don't do this, the system will think
that an AnimComp in the sequence points to a second bird instead of to the
one now animated.
Next there is the pointers NextSeq and PrevSeq. From one position you can
define many positions (as bobs) and then have the animation system page
through your sequences. This is similar to the old "Thumb movie books"
which simulated animation when you rapidly paged through a series of
pictures. Each new page of the bob creates the animation effect.
The next step is to set the sequence to cycle the pages. The pointers
NextSeq and PrevSeq point to the next and previous page or AnimComp.
These pointers create a closed ring. This means that you connect all the
AnimComps to each other with the pointers NextSeq and PrevSeq. The
previous AnimComp for the first AnimComp is the last AnimComp.
The next AnimComp from the last AnimComp is the first AnimComp.
PAGE 480
-----------------------------------------------------------------------------
Setting the RINGTRIGGER flag in the AnimComps(AnimComp.Flags = RINGTRIGGER),
which defines the ring, klls the system to flip the pages for the different
AnimComps. You can also set the length of time a specific AnimComp should be
displayed.
The variable AnimComp.TimeSet determines for how many Animate calls the
AnimComp will remain visible (Animate is the system routine that uses the
AnimObs). Animate copies the variable TimeSet to the variable Timer at the
beginning of a sequence. Timer is decremented with each Animate. Whenever
Timer equals zero, the next AnimComp in the sequence is displayed.
Now we will continue to define AnimComps and AnimObs. Just as a bob must
know which AnimComp it belongs to, the AnimComp must also know which bob it
represents. To accomplish this we point the AnimComp.AnimBob poinkr to the
specific bob.
To add something special, you can also specify one of your own routines
that will be executed each time you call Animate to display your AnimComps.
The pointer AnimComp.AnimCRoutine points to your function. Simply set this
pointer to zero when you haven't
PAGE 481
-----------------------------------------------------------------------------
defined a function. When using this function you must remember that it
returns a word value to your program. This value is not passed to the
system. Because this declaration affects the AnimComp structure, you should
check the returned value for any warning from the compiler.
Similar to the collision routines that are used with vsprites and bobs,
your functions can use the current AnimComp structure. For example, they
can check for a position and determine a specific action, or determine
object distances and react.
We are almost finished with our discussion of the AnimComp structure. But
before we explain our last point, we will discuss the AnimOb structure .
The AnimOb structure can contain many sequence rings. For example, it can
contain the arms, legs, body and the head of a man. All of these are
connected to each other and are able to move independently. We define the
components as a ring sequence which is automatically sequenced by Animate.
We represent the body with a single AnimComp structure because the body
itself usually does not move while walking.
The two pointers PrevComp and NextComp point to the AnimComps that display
the front and back view of the man. To link the AnimComps with the AnimOb
we use another pointer in the AnimOb structure. The pointer AnimOb.HeadComp
poinls to the first AnimComp that contains the rest of the objects.
(You link the components together with PrevComp and NextComp). Each
AnimComp contains a pointer back to the AnimOb. The pointer AnimComp.HeadOb
always points to the AnimOb in which the AnimComps are included.
This way you can easily access, with your routines, the required AnimOb
through the AnimComp structure.
However, more is required in order to initialise an animOb structure.
We still must determine where the structure will appear on the scrcen.
To solve this problem we use the variables Animob.Anx and AnimOb.AnY.
You cannot specify a coordinate using, for example, 160,100.
To specify the Animob coordinates, you must use a type of fixed decimal
method. The lower six bits are positioned after (to the right of) the decimal
point. To position your Animob you must multiply the RastPort coordinate
by 64.
You may be wondering why we are using such a strange positioning method.
However, remember that these variables set not only the objects' position
but also the velocity.
With each call of Animate the values from AnimOb.XAccel and AnimOb.YAccel
(X/Y movement) are added to AnimOb.XVel and
PAGE 482
-----------------------------------------------------------------------------
AnimOb.YVel (speed). The speed is then added to the position set by
AnimOb.Anx and AnimOb.AnY.
Using normal pixel values for position, speed, and movement could make your
Animob race across the screen. However, it wouldn't be very useful to have
Animob that disappears from the screen after the fifth call to Animate.
To prevent this, an Animob is moved only one pixel for every 64.
At first, it seems like this will be a problem. Multiplying by 64 is
possible, but using normal methods to move our Animob anywhere in
a RastPort presents a challenge. For the positions (Anx and Any) we have #
only 16 bits available. Normally this would provide values from -32768 to
+32768. But dividing this value by 64, gives us a range of -512 to +512.
So in order to position an object at an X coordinate of 629 in a hi-res
RastPort we have to use a trick instead of the normal methods.
We can now explain the last feature of AnimComps. It is possible to specify
the position of the individual animation components relative to animation
objects (also in steps of 64).
When you use an offset of 128*64 in AnimComp.XTrans for your animation
components you can reach any coordinate on the screen. Set positions smaller
than 128 (values between -128 and zero) in AnimOb.AnX. Values between -512
and +512 for the Y position work in any resolution. To set your components
relative Y positions, use the variable AnimComp.YTrans.
Two other variables that can be used to position an object are RingxTrans
and RingYTrans. Simply add, wilhout any changes, the value of these variables
to the current position. If you do not require any speed or motion, just
set the corresponding AnimOb variables(Xvel, YVel, XAccel and YAccel ) equal
to zero. Then initialise RingXTrans and RingYTrans with your desired values.
Make sure your speed is uniform otherwise it will affect your animation
sequences. You must synchronize the internal movements of an object
(like the wings of a bird or rotation of a wheel) with any position changes.
For example, the rotation of a wheel being slower than the forward movement
as you increase the forward speed and the wheel always rotates at the same
speed.
You can also specify a routine for your animation object that is called by
Animate. The poinler for this routine is named AnimORoutine. It is also of
the type word and you must specify the AnimOb, not the component
PAGE 483
-----------------------------------------------------------------------------
Now that we have initialised all the animation structures, the bob,
the component and the object, the only thing left to do is to display it on
the screen.
Again we need a completely initialised GelsInfo structure used for bobs and #
linked with a RastPort.
By using AddAnimOb(&AnimOb,&Key,&RastPort) we add all bobs and components of
the AnimOb to the GelsInfo structure. A required entry named Key is simply a
pointer to an AnimOb (struct AnimOb *Key = 0) that must be set to zero for
the first AddAnimOb call.
Because a list doesn't exist for the Animobs, you must know which AnimOb was
entered last in the GEL list. This helps ensure that the objects have been
properly linked. Also link the Animobs together by using the Animob.PrevOb
and AnimOb.NextOb pointers. The Key always points to the last entered Animob.
AddAnimOb handles more than linking the objects and entering the bobs in the
GEL list. It also sets the Timer variable for the AnimComps to the value
previously set in TimeSet. This permits decrementing the Timer.
Once you have processed all of the Animobs wilh AddAnimOb you are ready to
begin. Call Animate and the Timer variable for the current AnimComps is
decremented. When Timer == 0 the next sequence is activated. The position
controlled by RingXTrans, RingYTrans, Xvel, YVel, XAccel, YAccel, Xtrans and
YTrans is Calculated and then used lo display the next bob.
When you call SortGList and DrawGList as usual, your AninObs are displayed on
the screen.
18.3.1 Collisions with AnimObs
Because the smallest element used to display AnimObs are bobs, you can also
use them for collision control. Set the HitMask and Memask in the vsprite
structure of the bobs (using the same values for all bobs in one AnimComp
loop). Then you use SetCollision with your routine and test for collisions.
We have provided another example program so that you can actually see what
happens. This animation displays a flying seagull with flapping wings
(in one Animob):
PAGE 484
-----------------------------------------------------------------------------
/****************************************************************/
/* LetsAnimate.c */
/* */
/* This program displays and moves an Amiga AmimOb */
/* (here a Segull and uses AnmiComps (different */
/* wing positions */
/* Compiled with Aztec C V3.6a */
/* cc +L -S LetsAnimate.c */
/* ln LetsAnimate.o -1c32 */
/* (c) Program by Bruno Jennrich, Idea and Artwork by */
/* my little sister Ute. */
/****************************************************************/
#include "exec/types.h"
#include "exec/memory.h"
#include "exec/devices.h"
#include "devices/keymap.h"
#include "graphics/gfx.h"
#include "graphics/gfxmacros.h"
#include "graphics/copper.h"
#include "graphics/gels.h"
#include "graphics/gfxbase.h"
#include "graphics/regions.h"
#include "hardware/blit.h"
#include "hardware/custom.h"
#include "intuition/intuition.h"
#include "intuition/intuitionbase.h"
#include "libraries/diskfont.h"
#include "hardware/dmabits.h"
extern WORD MoveSeagull(); /*User AnimOb-Routine */
/* extern WORD Comp(); Optional AnimComp Routine */
#define RP Screen->RastPort /* Pointer to RastPort */
#define MAXBOBS 8 /* Seagull in in 8 Positions */
#define MAXCOORDS (MAXBOBS*2-2) /* Sequence consists of */
/* 14 pictures: 8 'to' */
/* and 6 'back'. */
struct GfxBase *GfxBase; /* BasePointer */
struct IntuitionBase *IntuitionBase;
struct NewScreen NewScreen = /* User Screen */
{
0,0,640,200,1,
1,0,
HIRES,
CUSTOMSCREEN,
NULL,
"",
NULL,NULL
};
struct Screen *Screen;
struct VSprite Start, Ende, /* VSprites for GEL */
BobsVSprite[MAXCOMPS]; /*List and Bobs */
struct Bob Bobs [MAXCOMPS]; /* User Bobs */
/* Note: 6 Bobs have the*/
/* same image!!! */
PAGE 485
-----------------------------------------------------------------------------
UWORD *BobBuffer;
/* MAXBOBS Bobs, 20 Lines of 3 WORDs for */
/* one BitPlane */
/* memory area for SAVEBACK */
/* In this example one buffer */
/* is enough, but because of */
/* the principle and to simply */
/* use new and other Bobs, */
/* we have given each Bob a */
/* 'SaveBuffer' */
UWORD *BobMask; /* Bob collisions-Masks */
/* Memory */
/* (20 Lines * 3 Words) */
UWORD BobBorderLine[MAXCOMPS][3]; /* Bobs Borderline */
/* Memory */
/* logical OR of all */
/* Bob lines in one */
/* line (here:3 Words) */
/*extern struct Custom custom; in custom.h */
/* pointer to Hardware */
/* Register for Copper */
struct UCopList *UCopList; /* own Copper List */
struct AnimComp AnimComp[MAXCOMPS];
/* seagull 'back and forth */
/* bit Start (Sequence 1) and */
/* end position (Sequence8) */
/* appear in each sequence */
/* only once, not twice */
/* like the other positions */
/* for the Seagull */
struct AnimOb *HeadOb = 0, /* Animations Key */
Seagull; /* our Seagull */
struct GelsInfo GelsInfo; /* GelsInfo initialization */
/* must be completed before */
/* using the Animation */
/* routine! */
UWORD *Image,*Help;
UWORD BobImage[MAXBOBS][20][3] =
{{
{0x0080,0x0000,0x0100}, /* Data for */
{0x0080,0x0000,0x0100}, /* Bob1. Only one */
{0x00c0,0x0000,0x0300}, /* BitPlane per */
{0x0040,0x0000,0x0200}, /* Bob */
{0x0060,0x0000,0x0600},
{0x0030,0x0000,0x0c00}, /* Please use the */
{0x0010,0x0000,0x0800}, /* copy function */
{0x0018,0x0000,0x1800}, /* of your editor */
{0x000c,0x0000,0x3000}, /* and save */
{0x0004,0x0000,0x2000}, /* yourself a lot */
{0x0006,0x0000,0x6000}, /* of work! */
{0x0003,0x0000,0xc000},
{0x0001,0x8001,0x8000},
{0x0000,0xc003,0x0000},
{0x0000,0x700e,0x0000},
PAGE 486
-----------------------------------------------------------------------------
{0x0000,0x1c38,0x0000}, /* Here is where */
{0x0000,0x0660,0x0000}, /* the data */
{0x0000,0x0180,0x0000}, /* for more */
{0x0000,0x0180,0x0000}, /* BitPlanes */
{0x0000,0x0180,0x0000} /* follows */
},
{
{0x0000,0x0000,0x0000}, /* Data for */
{0x0000,0x0000,0x0000}, /* Bob2. Only one */
{0x0200,0x0000,0x0040}, /* BitPlane. */
{0x0100,0x0000,0x0080},
{0x0080,0x0000,0x0100},
{0x0060,0x0000,0x0600},
{0x0030,0x0000,0x0c00},
{0x0018,0x0000,0x1800},
{0x000c,0x0000,0x3000},
{0x0006,0x0000,0x6000},
{0x0003,0x0000,0xc000},
{0x000l,0x8001,0x8000},
{0x0000,0xe007,0x0000},
{0x0000,0x300c,0x0000},
{0x0000,0x1818,0x0000},
{0x0000,0x0c30,0x0000}, /* Here is where */
{0x0000,0x0660,0x0000}, /* the data */
{0x0000,0x0180,0x0000}, /* for more */
{0x0000,0x0180,0x0000}, /* BitPlanes */
{0x0000,0x0180,0x0000} /* follows */
},
{
{0x0000,0x0000,0x0000}, /* Data for */
{0x0000,0x0000,0x0000}, /* Bob3. Only one */
{0x0000,0x0000,0x0000}, /* BitPlane. */
{0x0f00,0x0000,0x00f0},
{0x00c0,0x0000,0x0300},
{0x0060,0x0000,0x0600},
{0x0018,0x0000,0x1800},
{0x0006,0x0000,0x6000},
{0x0003,0x0000,0xc000},
{0x0001,0x8001,0x8000},
{0x0000,0x4002,0x0000},
{0x0000,0x2004,0x0000},
{0x0000,0x1008,0x0000},
{0x0000,0x0810,0x0000},
{0x0000,0x0c30,0x0000},
{0x0000,0x0660,0x0000}, /* Here is where */
{0x0000,0x0240,0x0000}, /* the data */
{0x0000,0x03c0,0x0000}, /* for more */
{0x0000,0x0180,0x0000}, /* BitPlanes */
{0x0000,0x0180,0x0000} /* follows */
},
{
{0x0000,0x0000,0x0000}, /* Data for */
{0x0000,0x0000,0x0000}, /* Bob4. Only one */
{0x0000,0x0000,0x0000}, /* BitPlane. */
{0x0000,0x0000,0x0000},
{0x3000,0x0000,0x000c},
{0x0f80,0x0000,0x01f0},
{0x0070,0x0000,0x0e00},
{0x000c,0x0000,0x3000},
{0x0003,0x0000,0xc000},
{0x0001,0x8001,0x8000},
{0x0000,0x6006,0x0000},
PAGE 487
-----------------------------------------------------------------------------
{0x0000,0x300c,0x0000},
{0x0000,0x1818,0x0000},
{0x0000,0x0c30,0x0000},
{0x0000,0x0420,0x0000},
{0x0000,0x0240,0x0000}, /* Here is where */
{0x0000,0x03c0,0x0000}, /* the data */
{0x0000,0x0180,0x0000}, /* for more */
{0x0000,0x0180,0x0000}, /* BitPlanes */
{0x0000,0x0180,0x0000} /* follows */
},
{
{0x0000,0x0000,0x0000}, /* Data for */
{0x0000,0x0000,0x0000}, /* Bob5. Only one */
{0x0000,0x0000,0x0000}, /* BitPlane. */
{0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000},
{0x7ff0,0x0000,0x0ffe},
{0x800f,0x0000,0x7001},
{0x0003,0x8001,0xc000},
{0x0000,0xc003,0x0000},
{0x0000,0x2004,0x0000},
{0x0000,0x1818,0x0000},
{0x0000,0x0810,0x0000},
{0x0000,0x0420,0x0000},
{0x0000,0x0660,0x0000},
{0x0000,0x0240,0x0000}, /* Here is where */
{0x0000,0x0180,0x0000}, /* the data */
{0x0000,0x0180,0x0000}, /* for more */
{0x0000,0x0180,0x0000}, /* BitPlanes */
{0x0000,0x0180,0x0000} /* follows */
},
{
{0x0000,0x0000,0x0000}, /* Data for */
{0x0000,0x0000,0x0000}, /* Bob6. Only one */
{0x0000,0x0000,0x0000}, /* BitPlane, */
{0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000},
{0x07e0,0x0000,0x07e0},
{0x3c3e,0x0000,0x7c3c},
{0x4003,0x8001,0xc001},
{0x0000,0x6006,0x0000},
{0x0000,0x300c,0x0000},
{0x0000,0x1818,0x0000},
{0x0000,0x0420,0x0000},
{0x0000,0x0660,0x0000},
{0x0000,0x03c0,0x0000}, /* Here is where */
{0x0000,0x0180,0x0000}, /* the data */
{0x0000,0x0180,0x0000}, /* for more */
{0x0000,0x0180,0x0000}, /* BitPlanes */
{0x0000,0x0180,0x0000) /* follows */
},
{
{0x0000,0x0000,0x0000}, /* Data for */
{0x0000,0x0000,0x0000}, /* Bob7. Only one */
{0x0000,0x0000,0x0000}, /* BitPlane. */
{0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000},
PAGE 488
-----------------------------------------------------------------------------
{0x03fc,0x0000,0x3fc0},
{0x0c0f,0x8001,0xe030},
{0x1000,0xe007,0x0008},
{0x2000,0x6003,0x0004},
{0x2000,0x1818,0x0004},
{0x0000,0x0c60,0x0000},
{0x0000,0x0660,0x0000},
{0x0000,0x0240,0x0000},
{0x0000,0x0240,0x0000}, /* Here is where */
{0x0000,0x0180,0x0000}, /* the data */
{0x0000,0x0180,0x0000}, /* for more */
{0x0000,0x0180,0x0000}, /* BitPlanes */
{0x0000,0x0180,0x0000} /* follows */
},
{
{0x0000,0x0000,0x0000}, /* Data for */
{0x0000,0x0000,0x0000}, /* Bob8. Only one */
{0x0000,0x0000,0x0000}, /*BitPlane. */
{0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000},
{0x0lfe,0x0000,0x7f80},
{0x0301,0xc003,0x80c0},
{0x0400,0x6006,0x0020},
{0x0800,0x1818,0x0010},
{0x0800,0x0c30,0x0010},
{0x1000,0x0420,0x0008},
{0x1000,0x03c0,0x0008},
{0x1000,0x0180,0x0008), /* the data */
{0x0000,0x0180,0x0000}, /* for more */
{0x0000,0x0180,0x0000}, /* BitPlanes */
{0x0000,0x0180,0x0000} /* would follow */
}
};
main()
{
int i,j,k;
char*LeftMouse = (char*)0xBFE001;
/* Left mouse button*/
if ((GfxBase = (struct GfxBase *)
OpenLibrary("graphics.library",0)) == NULL)
{
printf ("No Graphics !!!\n");
exit(0);
}
if ((IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library",0)) == NULL)
{
printf ("No Intuition !!!\");
goto cleanup2;
}
if((Screen = (struct Screen *)
OpenScreen(&NewScreen)) == NULL)
{
printf ("No Screen !!!\n);
goto cleanup3;
PAGE 489
-----------------------------------------------------------------------------
}
BobBuffer = (UWORD*) AllocMem(MAXCOMPS*20*3*sizeof(UWORD),
MEMF_CLEAR | MEMF_CHIP);
BobMask = (UWORD*) AllocMem(MAXCOMPS*20*3*sizeof(UWORD),
MEMF_CLEAR | MEMF_CHIP);
Image = (UWORD*) AllocMem(MAXBOBS*20*3*sizeof(UWORD),
MEMF_CLEAR | MEMF_CHIP);
if ((Image == 0) | (BobBuffer == 0) | (BobMask == 0))
{
printf ("No Chip Memory !!\n");
goto cleanup4;
}
Help = Image;
for (i=0; i<MAXBOBS;i++)
for (j=0;j<20;j++)
for (k=0;k<3;k++)
{
*Help = BobImage[i][j][k];
Help++;
}
SetRGB4(&Screen->ViewPort,0,2,8,151);
SetRGB4(&Screen->ViewPort,1,0,0,0,);
SetRast (&RP,0);
BltClear (&Start, sizeof(struct VSprite),0);
BltClear (&Ende, sizeof(struct VSprite),0);
BltClear (&GelsInfo, sizeof(struct GelsInfo),0);
BltClear (BobsVSprite,
sizeof struct VSprite)*MAXCOMPS,0);
BltClear (Bobs,
sizeof(struct Bob)*MAXCOMPS,0);
BltClear (AnimComp,
sizeof(struct AnimComp)*MAXCOMPS,0);
BltClear (&Seagull, sizeof(struct AnimOb),0);
/*****************************************************************/
/* A little Copper-Power */
/*****************************************************************/
UCopList = (struct UCopList *)
AllocMem (sizeof(struct UCopList),
MEMF_CHIP | MEMF_CLEAR);
CWAIT (UCopList,150,0);
CMOVE (UCopList,custom.color[0]),0x000f); /* Sea */
CEND (UCopList);
Screen->ViewPort.UCopIns = UCopList;
/* Copper list linked */
RemakeDisplay(); /* and calculate new */
/****************************************************************/
GelsInfo.sprRsrvd = 0xff; /* All Sprites for VSprites*/
PAGE 490
-----------------------------------------------------------------------------
/* Memory for Gelinfo reserved */
GelsInfo.nextLine = (WORD *)AllocMem(sizeof (WORD)*8,
MEMF_PUBLIC | MEMF_CLEAR );
GelsInfo.lastColor = (WORD *)AllocMem(sizeof (LONG)*8,
MEMF_PUBLIC | MEMF_CHIP);
GelsInfo.collHandler = (struct collTable *)
AllocMem(sizeof (struct collTable),
MEMF_PUBLIC | MEMF_CLEAR);
if ((GelsInfo.nextLine == 0) | (GelsInfo.lastColor == 0) |
(GelsInfo.collHandler == 0))
{
printf (" No Memory for GelsInfo !!!\n");
goto cleanup5;
}
GelsInfo.leftmost = 0; /* Boundary Collisions */
GelsInfo.rightmost = 640; /* Border collisions */
GelsInfo.topmost = 0;
GelsInfo.bottommost = 200;
InitGels(&Start, &Ende, &Gelsinfo);
/* GelsInfo initialization */
RP.GelsInfo = &GelsInfo; /* and in RastPort linked */
for (i=0; i<MAXBOBS; i++)
{
Bobs[il.BobVSprite = &BobsVSprite[i];
BobsVSprite[i].VSBob = &Bobs[i];
BobsVSprite[i].Width = 3; /* All Bobs are */
BobsVSprite[i].Height = 20; /* the same size */
BobsVSprite[i].Flags = SAVEBACK;
/* Store background */
/* (in BobBuffer) and */
/* restore it at a time */
BobsVSprite[i].Depth = 1;
/* Only one Plane per Bob */
/* BobsVSprite[i].ImageData */
/* initialised in extra loop*/
BobsVSpriter[i].PlanePick = 1;
/* Only first plane wriiten */
/* to Rast Port */
BobsVSprite[i].PlaneOnOff=0;
/* Remaining planes remain 0 */
BobsVSprite[i].CollMask = BobMask+i*20*3;
BobsVSprite[i].BorderLine = &BobBorderLine[i][0];
/* Memory for CollMask and Borderline */
/* prepared */
Bobs[i].ImageShadow = BobMask+i*20*3;
/* Shadow = CollMask */
Bobs[i].Flags = BOBISCOMP;
/* Bob is part of */
Bobs[i].BobComp=&AnimComp[i];
/* this Animcomps */
PAGE 491
-----------------------------------------------------------------------------
Bobs[i].SaveBuffer = BobBuffer+i*20*3;
/* Memory for SAVEBACK Option */
BobsVSprite[i].Y = 0; /* Position word is */
BobsVSprite[i].X = 0; /* calculated by the */
/* animation system! */
Bobs[i].Before = 0; /* Priorities too!!!!! */
Bobs[i].After = 0;
InitMasks (&BobsVSprite[i]);
/* Initialise CollMask and BorderLine. */
/* (Memory must already be set aside!! */
}
for (i=0; i<MAXBOBS; i++)
BobsVSprite[i].ImageData = Image+i*20*3;
for (i=MAXBOBS-2; i>0; i--)
BobsVSprite[MAXCOMPS[i].ImageData=
Image+i*20*3;
/* Order the Bobs for */
/* Sequence animation */
for (i=0; i<MAXBOBS; i++)
{
AnimComp[i].AnimBob = &Bobs[i] ;
AnimComp[i].PrevComp = 0; /* no further */
AnimComp[i].NextComp = 0; /* AnimComp in */
/* AnimOb */
AnimComp[i].TimeSet = 3; /* 3 mal Animate() */
/* before new sequence */
/* is displayed. */
AnimComp[i].Flags = RINGTRIGGER;
/* Ring-Sequence-Animation */
AnimComp[i].XTrans = 128*64;
AnimComp[i].YTrans = 0;
/* Offset to AM/AnY in Seagull */
/* Note: Fixed decimal ! ! ! */
AnimComp[i].AnimCRoutine = NULL; /* comp; */
/* no AnimComp Routine */
AnimComp[i].HeadOb = &Seagull;
/* HeadOb for AnimComp (for one */
/* routine as intersection mark!)*/
}
/*Sequence: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 */
/*Bobs/AnilComp: 1 2 3 4 5 6 7 8 9 6 5 4 3 2 */
for (i=MAXBOBS-2; i>0; i--)
{
AnimComp[14-i].AnimBob = &Bobs[i];
AnimComp[14-i].PrevComp = 0;
AnimComp[14-i].NextComp = 0;
AnimComp[14-i].TimeSet = 3;
AnimComp[14-i].Flags = RINGTRIGGER;
AnimComp[14-i].XTrans = 128*64;
AnimComp[14-i].YTrans = 0;
AnimComp[14-i].AnimCRoutine = NULL; /* Comp; */
Bobs[14-i].BobComp = &AnimComp[14-i];
AnimComp[l4-i].HeadOb = &Seagull;
} /* see above */
for (i=1; i<MAXCOMPS-1; i++)
{
PAGE 492
-----------------------------------------------------------------------------
AnimComp[i].NextSeq = &AminComp[i+1];
AnimComp[i].PrevSeq = &AnimComp[i-1];
/8 intitialize 'Ring' for Ring/Sequence */
/* Animation (PrevComp and NextComp remain */
/* here without action and in this case */
/* are not initialised, but set to 0 */
}
AnimComp[0].NextSeq = &AnimComp[1]; /* Close ' Ring ' */
AnimComp[0].PrevSeq = &AnimComp[13];
AnimComp[MAXCOMPS-1].NextSeq = &AnimComp[0];
AnimComp[MAXCOMPS-1].PreqSeq = &AnimComp[12];
Seagull.HeadComp = &AnimComp[0]; /* Animobs first */
/* AnimComp */
Seagull.RingXTrans = 2*64; /* X/Y Translation */
Seagull.RingYTrans = 1*64; /* of seagull */
Seagull.AnX = 0; /* start position */
Seagull.AnY = 0; /* of XTrans */
Seagull.XAccel = 0x0000; /* has no movement */
Seagull.YAceel = 0x0000;
Seagull.XVel = 0x0000; /* no movement speed */
Seagull.YVel = 0x0000;
Seagull.AnimORoutine = MoveSeagull;
/* User control routine */
AddAnimOb(&Seagull,&HeadOb,&RP);
/* Animob in list */
while (&LeftMouse & 0x40) == 0x40)
{
Animate(&HeadOb,&RP); /* Sort */
SortGList(&RP) ; /* Animation */
WaitTOF(); /* to prevent blinking the bobs! */
DrawGList(&RP, &Screen->ViewPort); /* Draw */
}
/* GelsInfo's memory freed */
cleanup5:
if (GelsInfo.nextLine != 0)
FreeMem(GelsInfo.nextLine, sizeof(WORD)*8);
if (GelsInfo.lastColor != 0)
FreeMem (GelsInfo.lastColor, sizeof(LONG)*8);
if (GelsInfo.collHandler != 0)
FreeMem (GelsInfo.collHandler,
sizeof(struct collTable));
cleanup4:
if (Image != 0)
FreeMem(Image,MAXBOBS*20*3*sizeof(UWORD));
if (BobBuffer != 0)
FreeMem(BobBuffer,MAXCOMPS*20*3*sizeof(UWORD));
if (BobMask != 0)
FreeMem(BobMask, MAXCOMPS*20*3*sizeof(UWORD));
cleanup3: CloseScreen(Screen);
cleanup2: CloseLibrary(IntuitionBase);
cleanup1: CloseLibrary(GfxBase);
}
/*****************************************************************/
/* This function is called each time by Animate() */
/*---------------------------------------------------------------*/
PAGE 493
-----------------------------------------------------------------------------
/* Input parameter : AnimOb-Structure, animated with */
/* Animate(). These parameters are */
/* passed by Animate() */
/*--------------------------------------------------------------*/
/* Returnvalue : none */
/****************************************************************/
WORD MoveSeagull (Object)
struct AnimOb *Object;
{
if ((Object->AnX < (-128*64)) || /* 1st user object */
(Object->AnX > ((512-48)*64))) /* corner? */
Object->RingXTrans *= -1;
if ((Object->AnY < (0)) ||
(Object->AnY > (120*64)))
Object->RingYTrans *= -1;
}
/*****************************************************************/
/* This function is called each time by Animate() */
/*---------------------------------------------------------------*/
/* Input parameter : AnimOb-Structure, animated with */
/* Animate(). These parameters are */
/* passed by Animate() */
/*---------------------------------------------------------------*/
/* Returnvalue : none */
/*****************************************************************/
/* WORD Comp(Component)
struct AnimComp *Component;
{
return(0);
} */
PAGE 494
-----------------------------------------------------------------------------
19. Copper Programming in C
As you already know from the previous chapters, the Copper is a coprocessor
of the Amiga. It is responsible for the visible display, which means that
it determines what appears at a specific position of the electronic beam.
The Copper also helps display sprites and vsprites However, a more
important feature of the Copper is that it can be programmed by the user.
Simply insert a pointer to the user Copper list (struct UCopLiSt
*UserCopperList), which uses the Copper instructions to program the Copper.
However, before you can use this you must assign enough memory for
your user Copper list: UserCopperList = (struct UCopList *) AllocMem(sizeof
(struct UCopIns), MEMF_PUBLIC | MEMF_CLEAR).
You must clear the memory for this structure. Do this either directly
with AllocMem through the MEMF-CLEAR option, or afterwards with BltClear.
This allows the entry of new Copper instructions and then tells MakeVPort
that the user Copper list is still empty.
Now that we have explained all the preliminary steps, we can proceed to the
Copper language. It is very simple and concise of only three instructions,
CMOVE, CWAIT and CEND. These three instructions are all that is needed
to program pull down Intuition screens.
The CMOVE instruction enables you to write a value into a specific hardware
register (see Appendix C). Both the hardware register and the value are
specified by you with the Custom structure, which allows you to access the
hardware registers. To create this structure first use extern struct Custom
custom and then use custom.<Registername> to access the individual
hardware registers.
Now give the CMOVE instruction as a parameter and, as you may have assumed,
the absolute address of the desired hardware register. The Copper only
works with offsets of the registers from $DF000 and CMOVE calculates the
absolute address for you.
You must provide a pointer to this structure beforehand so that the CMOVE
instruction also knows where to find the user Copper list.
PAGE 495
-----------------------------------------------------------------------------
Now you must supply the 16 bit value (Word) that will be wrilten into
the desired hardware register.
A complete call with the CMOVE instruction would look like this:
CMOVE (UserCopperList, Custom.<RegisterName>, Value);
There is a small restriction you should remember when using the CMOVE
instruction. Usually you can write to any hardware register numbered higher
than $20 (dskpt) without any limitations. However, you cannot under any
circumstances, address register numbers smaller than $10 (adkconr) through
the Copper. It is possible to write only to registers that fall between $10
and $20 after you have set the Copper DangerBit in register (copcon)
(number $2E).
When discussing sprite collision detection, we explained how you
access the hardware registers with help from the 68000. Review that
section if necessary.
Another Copper instruction is CWAIT. This instruction enables you to
wait for the electronic scanning beam to reach a specific position. The
user Copper list doesn't perform any other instructions until the
scanning beam reaches the specified position (The Copper program
won't have any effect on your C program). For example, you could wait
for any desired position and change the contents of one of the color
registers. You could also use this technique to display one of your
sprites beginning in the middle of the screen.
When you use the CWAIT instruction you must tell the user Copper list
where your instructions will be located. You must also provide the X and
Y position that the electronic beam should wait for. The order of the X and
Y coordinates is very important. First specify the Y coordinate and then
the X coordinate. Pay close attention to the order of these coordinates
because using them out of sequence can be very frustrating. Your Copper
program will not function properly if the Y coordinate isn't first.
CWAIT (&UserCopperList,Y,X) lets you wait for a specific electronic beam
position. Remember that the Y position must be smaller than 263 and the X
position must be smaller than 223. Also, you must set the Y position
relative to the top of your ViewPort and the X position relative to the
normal scanning position. This means that for the X position you have to
consider Overscan. The electronic beam actually covers a much larger area
than is visible on the screen. A good value to use for positioning the
electronic beam at The left ViewPort border is X=60 plus or minus 2 or
View.DxOffset/2 plus or minus one.
PAGE 496
-----------------------------------------------------------------------------
So that the Copper program ends properly, we use the CEND instruction.
The only parameter needed is the user Copper list that will be ending.
CEND (&UserCopperList) waits for the electronic beam to reach row position
10000 and column position 256. Since this position is never reached,
the user Copper list is no longer used.
When the electronic beam reaches the bottom of the screen, it will start at
the top row again (Top Of Frame). All Copper lists for the ViewPorts and the
user Copper Iist are run again.
The Copper can perform raster row interrupts similar to the ones from the
Commodore 64. However, unlike the Commodore 64, the Copper can also change
a color in the middle of a raster row. Remember that each CMOVE instruction
requires a maximum resolution of 8 pixels. This means that with a normal
resolution, a CMOVE instruction can only by performed every 8 pixels.
Therefore, between two consecutive CMOVE instructions there must be an 8
pixel gap.
The CwAIT instruction allows you to wait for electronic beam positions that
are spaced only 4 pixels apart. However, When a CMOVE instruction follows a
CWAIT instruction, an 8 pixel gap is still required.
After using the above instruction to create your user Copper list, you must
provide this information to the ViewPort that will use the list. To do this
use ViewPort.UCopIns = UserCopperList. When using Intuition screens, use the
following form, Screen>ViewPort.UCopIns = &UserCopperList.
Now open your own screens by calling MakeVPort and MrgCop.
Intuition screens are handled differently. OpenScreen generates the Copper
list for the screen. Afterwards, use RemakeDisplay to ensure that the new
user Copper list is added to the global View Copper list.
FreeVPortCprList and CloseScreen release the dynamically reserved memory for
the UCopList, a two word pointer that contains your instructions. No
additional instructions, such as FreeMem need to be executed. Make sure you
declare your user Copper list as a pointer and reserve the required memory
for the UCopList structure in your program. FreeVPortCprList and CloseScreen
free the memory for not only the instruction list, but (also for the
UCopList Structure.
When you declare the UCopList as a normal structure, the memory that it uses
is released twice. It is released first by FreeVportCopLists and then by
your program, which ends by
PAGE 497
-----------------------------------------------------------------------------
returning all used memory areas to the system. This double release of one
memory area causes the familiar Guru Meditations.
To avoid this, always declare your UCopList as a pointer that is later used
to assign your memory.
Finally, another small tip: To change your Copper list in your program you
must clear your reserved UCopList structure (BltClear is best) and build a
new list.
/***********************************************************************/
/* Copper. c */
/* */
/* This Program demonstrates how you can access the */
/* AMIGA Hardware-Registers with Help from the Copper. */
/* Compiled with: Aztec C 3.6a */
/* cc +L -s Copper.c */
/* ln Copper.0 -lc32 */
/* (c) Bruno Jennrich */
/***********************************************************************/
#include "exec/types.h"
#include "exec/nodes.h"
#include "exec/memory.h"
#include "graphics/gfx.h"
#include "graphics/gfxmacros.h"
#include "graphics/gfxbase.h"
#include "graphics/text.h"
#include "graphics/regions.h"
#include "graphics/clip.h"
#include "graphics/view.h"
#include "graphics/copper.h"
#include "graphics/gels.h"
#include "hardware/blit.h"
#include "hardware/custom.h"
#define WIDTH 320
#define HEIGHT 200
/* PAL 256 HERE */
#define MODES 0
struct View View;
struct ViewPort ViewPort;
struct RasInfo RasInfo;
struct BitMap BitMap;
struct RastPort RastPort;
struct GfxBase *GfxBase;
struct View *oldview;
struct UCopList *UserCopperList; /* our Copper List */
extern struct ColorMap *GetColorMap();
/* extern struct Custom custom; in custom.h */
/* For Access to the */
/* Hardware-Register */
PAGE 498
-----------------------------------------------------------------------------
UWORD Colors[16l = {
0x000,0x0bbd,0x0f0,0xf00,
0x123,0x435,0x678,0x009,
0x123,0x435,0x678,0x009,
0x123,0x435,0x678,0x009
};
/* Own ColorMap. */
/* Color reg. 1 is */
/* changed by the */
/* Copper */
char *LeftMouse = (char *)0xbfe001;
char *Texts[15] = {"COPPER-Programming with the AMIGA",
"";
"The SPECIAL-EFFECTS Processor in Action";
"";
"";
"Colors underneath the Text";
"(a standard feature of Games)",
"and how it is done.";
"";
"";
"";
"This Effect is especially spectacular";
"when used with Moving BOBS !";
"";
"(MOUSE BUTTON)};
/**************************************************************/
/* Here we go ! */
/**************************************************************/
main()
{
long i,Len;
if ((GfxBase = (struct GfxBase *)
Open Library ("graphics.library",0)) == NULL )
{
printf (" No Graphics !!!\n");
Exit(10);
}
oldview = GfxBase->ActiView; /* Build a Screen as */
InitView(&View); /* usual */
InitVPort(&ViewPort);
View.Modes = MODES;
View.ViewPort = &ViewPort;
ViewPort.DWidth = WIDTH;
ViewPort.DHeight = HEIGHT;
ViewPort.Modes = MODES;
RasInfo.RyOffset = 0;
RasInfo.RxOffset = 0;
RasInfo.Next = 0;
ViewPort.RasInfo = &RasInfo;
ViewPort.ColorMap = GetColorMap(l6);
PAGE 499
-----------------------------------------------------------------------------
LoadRGB4 (GViewPort, &Colors, 16) ;
InitBitMap(@BitMap, 4, WIDTH, HEIGHT);
for (i=0; i<4; i++)
Bitmap.Planes[i].(PLANEPTR)
AllocRasteR(WIDTH,HEIGHT);
if (BitMap.Planes[i] == NULL)
{
printf("No BitMap - Space !!!\n");
Exit(0);
}
InitRastPort(&RastPort);
RastPort.BitMap = &BitMap;
RasInfo.BitMap = &BitMap;
SetRast (&RastPort,0);
SetAPen (&RastPort,1);
for (i=0;i<17;i++)
{
Len = WIDTH/2-
TextLength(&RastPort,Texts[i], strlen(Texts[i]))/2;
Move (&RastPort, Len,i*9+63+RastPort.TxBaseline);
/* Y-Coordinate should be divisible by 9 ! */
Text (&RastPort,Texts[i],strlen(Texts[i]));
MakeVPort(&View,@ViewPort); /* Display ViewPort. */
MrgCop(&View); /* Makes the difference */
LoadView(&View); /* visible. */
UserCopperList = (struct UCopList *)
AllocMem(sizeof (struct UCopList),MEMF_CHIP);
/* Reserve the required Memory */
/* for the UCopList-Structure */
BltClear(UserCopperList, sizeof(struct UCopList),0);
/* Clear UCopList-Structure */
for (i=0; i<256; i+=9)
{
CWAIT (UserCopperList,i,view.DxOffset/2);
CMOVE (UserCopperList,custom.color[1],0x0fff);
/* white */
CWAIT (UserCopperList,i+3,view.DxOffset/2);
CMOVE (UserCopperList,custom.color[1],0x0bbd);
/* light purple */
CWAIT (UserCopperList,i+5,View.DxOffset/2);
CMOVE (UserCopperList,custom.color[1],0x088b);
/* purple */
CWAIT (UserCopperList,i+7,View.DxOffset/2);
CMOVE (UserCopperList,custom.color[1],0x0558);
/* dark purple */
}
PAGE 500
-----------------------------------------------------------------------------
CEND (UserCopperList ); /* End UCopList */
Delay (100); /* Wait 2 Seconds */
ViewPort.UCopIns = UserCopperList;
/* Link ViewPort and UCopList */
MakeVPort (&View,&ViewPort);
/* Calculate ViewPort Copper-List */
/* with a Intuition Screen using */
/* RethinkDisplay() */
MrgCop(&View);
LoadView(&View);
while ((*LeftMouse @ 0x40) == 0x40);
/* Wait for Mouseclick */
LoadView (oldview);
for (i=0; i<4; i++)
FreeRaster (BitMap.Planes[i],WIDTH, HEIGHT);
FreeColorMap(ViewPort.ColorMap);
FreeVPortCopLists(&ViewPort);
/* UCopList automatically released */
FreeCprList(View.LOFCprList);
FreeCprList(View.SHFCprList);
/* View-Copper List FREE */
CloseLibrary(GfxBase);
return (0);
}
PAGE 501
--------------------------------------------------------------------------
APPENDIX A: STRUCTURE AND INCLUDE FILES.
This appendix contains a listing of all symbolic constants (#define xyz
numerical value) and the include file in which these constants are
located. Also listed are all used structures (struct) and all used C
macros (#define xyz()). At the end of this appendix we explain the structure
functions and provide more details for the most important structure
details.
Declaration Include File.
------------------------------ ----------------------------------
struct AnimOb "graphics/gels.h"
struct AnimComp "graphics/gels.h"
struct AreaInfo "graphics/rastport.h"
#define AREAOUTLINE "graphics/rastport.h"
struct AvailFonts "libraries/diskfont.h"
struct AvailFontsHeader "libraries/diskfont.h"
struct BitMap "graphics/gfx.h"
struct Bob "graphics/gels.h"
#define BNDRYOFF() "graphics/gfxmacros.h"
#define BOBISCOMP "graphics/gels.h"
#define BOBSAWAY "graphics/gels.h"
#define BOTTOMHIT "graphics/collide.h"
#define CEND0 "graphics/gfxmacros.h"
#define CMOVE0 "graphics/gfxmacros.h"
struct ColorMap "graphics/view.h"
#define COMPLEMENT "graphics/rastport.h"
struct Custom "hardware/custom.h"
#define CUSTOMBITMAP "intuition/intuition.h"
#define CUSTOMSCREEN "intuition/intuition.h"
#define CWAIT0 "graphics/gfxmacros.h"
struct DBuffPacket "graphics/gels.h"
#define DUALPF "graphics/view.h"
#define EXTRA_HALFBRITE "graphics/view.h"
struct GelsInfo "graphics/gels.h"
#define GELGONE "graphics/gels.h"
struct GfxBase "graphics/gfxbase.h"
#define HAM "graphics/view.h"
#define HIRES "graphics/view.h"
#define INVERSVID "graphics/rastport.h"
struct IntuitionBase "intuition/intuitionbase.h"
struct IntuiMessage "intuition/intuition.h"
PAGE 503
---------------------------------------------------------------------------
#define JAM1 "intuition/intuition.h"
#define JAM2 "intuition/intuition.h"
#define LACE "graphics/view.h"
#define LEFTHIT "graphics/collide.h"
struct NewScreen "intuition/intuition.h"
struct NewWindow "intuition/intuition.h"
#define MEMF_CHIP "exec/memory.h"
#define MEMF_PUBLIC "exec/memory.h"
struct Menu "intuition/intuition.h"
struct MenuItem "intuition/intuition.h"
#define OVERLAY "graphics/gels.h"
#define PFBA "graphics/view.h"
#define RASSIZE() "graphics/gfx.h"
struct RasInfo "graphics/view.h"
struct Rastport "graphics/viewport.h"
#define RemBob() "graphics/gels.h"
#define RINGTRIGGER "graphics/gels.h"
#define RIGHTHIT "graphics/collide.h"
struct Screen "intuition/intuition.h"
#define SAVEBACK "graphics/gels.h"
#define SAVEBOB "graphics/gels.h"
#define SUSERFLAGS "graphics/gels.h"
#define SELECTDOWN "intuition/intuition.h"
#define SELECTUP "intuition/intuition.h"
#define SetOPen() "graphics/gfxmacros.h"
#define SetDrPt() "graphics/gfxmacros.h"
#define SetWrMsk() "graphics/gfxmacros.h"
#define SetAfPt() "graphics/gfxmacros.h"
struct SimpleSprite "graphics/sprite.h"
#define SPRITE_ATTACHED "graphics/sprite.h"
struct TextAttr "graphics/text.h"
struct TextFont "graphics/text.h"
struct TmpRas "graphics/rastport.h"
#define TOPHIT "graphics/collide.h"
struct UCopList "graphics/copper.h"
typedef ULONG "exec/types.h"
typedef UWORD "exec/types.h"
struct View "graphics/view.h"
struct ViewPort "graphics/view.h"
#define VP_HIDE "graphics/view.h"
struct VSprite "graphics/gels.h"
#define WBENCHSCREEN "intuition/intuition.h"
struct Window "intuition/intuition.h"
PAGE 504
-----------------------------------------------------------------------------
struct AnimComp
{
WORD Flags;
THese variables enable you to determine the type of
animation to use. When you set the RINGTRIGGER flag it
means you have set up a ring of ANIMCOMPS. You link the
ring through the AnimComp.NextSeq and AnimComp.PrevSeq.
Animate can automatically display different sequences
(like a flying bird) by using the AnimComp ring.
Unless you set RINGTRIGGER, animation is not possible.
WORD Timer;
This variable is loaded with the timeset variable and
decremented (if set to decrement to zero) with each
Animate() call. Whenver Timer reaches zero, depending on
your setup (RINGTRIGGER), a new sequence is displayed.
WORD TimeSet;
The value contained here is written into Time and
decremented there by every Animate() call. TimeSet
determines how long an animnation sequence is active. The
next sequence starts after a certain number of Animate()
calls.
struct AnimComp *NextComp;
struct AnimComp *PrevComp;
These two variables allow you to link many animation
objects (AnimOb) together for display by Animate(). For
example, the AnimObs for the arms, legs and head of a man
can be linked together. Please remember that NextComp and
PrevComp should not be used to animate a sequence for
moving an arm while walking. You must use NextSeq and
PrevSeq for these type of animations.
struct AnimComp *NextSeq;
struct AnimComp *PrevSeq;
When you want to repeatedly change an animation component
define different display (sequences) of an object (for
example, an arm). Then use the above two pointers to tell
Animate() that you want the arm displayed in different
positions. You program the various arm movement positions
and then they are displayed.
WORD (*AnimCRoutine)();
You either set this pointer to zero or point it to a
function you have defined. Each call of Animate() that
displays your components also calls this function. Your
routine is passed to the current AnimComp structure.
PAGE 505
-----------------------------------------------------------------------------
WORD YTrans, XTrans;
These two pointers contain the position of the AnimComps
relative to the AnimObs defined earlier. (Please remember
to use the fixed decimal arithmetic for these variables).
struct AnimOb *HeadOb;
This pointer points to the previously defined AnimOb of
which the AnimComp is a part.
struct Bob *AnimBob;
Naturally Animate() must also know what should be
displayed. For this purpose the AnimComp structure contains
a pointer to the bob this is associated with the AnimComp.
(Please make sure that the bob also has its own VSprite
structure).
}
The AnimComp, or the animation components, determine the connection between
bob and animation object (AnimOb). This is especially important with
Sequence Animation (RINGTRIGGER) because it connect the individual
components together in a ring and sets the amount of time each sequence is
active.
-------------------------------------------------------
struct AnimOb
{
struct AnimOb *NextOb *PrevOb;
The variables mkae it possible for you to link many
animation object together. The linked objects are then
animated with Animate() and then with SortGList().
DrawGList() etc are all displayed on the screen (for
example several men).
LONG Check;
This variable contains a count of the calls to Animate()
that have been used for an AnimOb.
WORD AnOldY AnOldX;
These variables contain the old position of an animation
object. We save the old position because the current
position (AnX, AnY) does not change until timer reaches
zero for the current AnimComp. The user can change the
position between movements which causes some components to
be displayed in the wrong positions. For this reason, we
store the old position. After numerous Animate() calls the
actual position is calculated using the old position and
the following variables.
WORD AnX, AnY;
These variables contain the actual positions of the AnimObs.
They do not contain values for pixel and row positions
within a RastPort. Depending on the speed and motion
variables, they contain values in steps of 64 for pixels
and lines.
PAGE 506
-----------------------------------------------------------------------------
This means you must use AnX = Width/2 * 64 and
AnY = Height/2 * 64 to move AnimOb to the middle of the
screen. Again we have a problem using horizontal values
plus or minus 32768 versus positions over 512 (=32768/64).
The following trick can help: The variable XTrans (and
YTrans) in the AnimComp structure set the position of an
AnimComp relative to the previously defined AnimOb. When
you simply initialise XTrans with a value of 128*64 you
can move an object around the entire screen (512+128 = 640)
even in hires mode. For horizontal values less than 128
you simply use negative values with AnX.
WORD YVel, XVel;
The speed of an AnimOb is contained in these two variables.
The values in YVel and XVEL and added to AnY and AnX
after every Animate() call. Because Animate() is normally
called many timed per second it is possible for your object
to move erratically on the screen. To prevent this,
velocity and acceleration are set using step values of 64
for every Animate() (this is the reason for the unusual
method used for the values in AnX and AnY). This means that
with a value of one in XVel, 64 Animate calls have to
occur before the object moves one pixel.
WORD YAccel, XAccel;
These variables determine the motion of your AnimOb. These
variables must also be set in steps of 64. The values in
XAccel and YAccel are added to XVel and YVel.
WORD RingYTrans, RingXTrans;
These variables set the speed of the AnimOb. They are added
directly to AnX and AnY. Motion isn't a factor here.
WORD (*AnimORoutine) ();
The routine whose addres is specified here is called once
by every Animate() call. This routine is passed to the
current AnimOb stucture so that the actual position of the
current AnimOb is controlled and the proper reaction is
received.
struct AnimComp *HeadComp;
This pointer points to the first animation component of an
AnimOb.
AUserStuff AUserExt;
Link your own structures (see VSPRite, VUserStuff) here.
}
The AnimOb structure contains a complete animation object. You use
AddAnimOb() to make this structure available to the system and then use
Animate() for animation.
PAGE 507
-----------------------------------------------------------------------------
struct AvailFonts
{
OWORD af_Type;
These variables determine whether the TextAttr structure
specified below uses a font in memory (AFF_MEMORY) or a
diskfont in the "SYS:fonts" directory (AFF_DISK). This is
important for determining whether you should use OpenFont()
or OpenDiskFont() to open a font.
struct TextAttr af_Attr;
This is the TextAttr structure returned by AvailFonts().
}
This structure is only used by the routine AvailFonts() (and by you, of
course). It is written after the AvailFontsHeader is located in a memory
area where it is available for use by AvailFonts().
--------------------------------------------
struct AreaInfo
This structure is required for the Area function. It is initialised with
InitArea and used for the coordinates of a polygon corner points.
--------------------------------------------
struct AvailFontsHeader
This structure can only be created by using the routine AvailFonts() and
contains only one variable: afh_NumEntries. This variable contains the
count of the AvailFonts structures written after the AvailFontsHeader in
the memory area specified by the AvailFonts() routine.
--------------------------------------------
struct BitMap
{
UWORD BytePerRow;
This variable contains the byte count required for one
bitmap row (BytesPerRow = Width/8).
UWORD Rows;
The line count for a bitmap (height) is contained in this
variable.
UWORD Flags;
This variable is only used by the system.
PAGE 508
-----------------------------------------------------------------------------
UBYTE Depth;
The number of bitplanes in a bitmap are contained in this
variable. Please remember that the depth determines the
number of available colours (colors = 2^NumBitPlanes).
UWORD pad;
This is one full WORD so the following pointer begins with
a LONG WORD address.
PLANEPTR Planes[8];
These eight pointers contain the addresses of the
individual bitplanes for the bitmap. Although now you can
only use six of the eight pointers you can see that there
are possibilities for future expansions.
}
The BitMap structure contains the addresses for the individual memory areas
where graphics are stored. In addition, information for the height, width
and depth of the bitmap are contained here.
--------------------------------------------
struct Bob
{
WORD Flags;
Through these variables the user can determine how the bob
is handled by the system. The SAVEBOB flag tells the system
that once the bob is drawn it won't be cleared from the
RastPort (brush function). You use BOBISCOMP to make the
bob part of an animation component. Make sure that you
also point the pointer BobComp to the corresponding
AnimComp structure.
Not only the user can set the bob flags, the system can
also set the so-called status flags. These flags provide
information about the status of a bob. For example, the
flag BOBNIX tells us that the bob has disappeared from the
RastPort, the background has been restored, and the BOB
was removed from the GEL list.
WORD *SaveBuffer;
This pointer points to a memory area, reserved by you,
where the background will be stored when a bob is drawn.
Because bobs are normally written directly into the bitmap,
the background where the bob appears is destroyed. When you
set the SAVEBACK flag in the vsprite structure the background
is saved to the memory area. This area must be at least as
wide an high as the bob being drawn. You must also make sure
that for every bitplane of the RastPort being written to
(see PlanePick and planeOnOff in the VPsrite structure) a
buffer in chip memory is reserved. The background is
saved into these memory buffers.
PAGE 509
-----------------------------------------------------------------------------
WORD *ImageShadow;
As you may already know, you define a bob bitplane by
bitplane and use PlanePick and PlaneOnOff to determine in
which plane the bob is drawn. ImageShadow points to a
memory buffer that is large enough to store one bitplane
of your bob. All the set pixels in the individual bitplanes
for your bob are stored in ImageShadow. In other words, all
the Bob-Planes are ORed and stored in ImageShadow (chip
memory).
struct Bob *Before;
struct Bob *After;
These two pointers determine the order the bobs are drawn.
They can be used to make the GEL routines use your bobs in a
specific order. However, since this function removes
pointers, you must do this after AddBob().
struct VSprite *BobVSprite;
Each bob requires a vsprite structure because the bob
structure doesn't contain any variables for positioning.
In addition, the GEL list is made up of only vsprite
structures and the bob must be in this list somehow. To
make this work, this pointer points to the vsprite structure
for the bob (every bob has its own).
struct AnimComp *BobComp;
This pointer points to the AnimComp structure to which the
bob belongs. You set this pointer only after setting the
flag BOBISCOMP.
struct DBuffPacket *DBuffer;
When you want to use bobs with a double buffered bitmap,
which saves both bitmaps for the background, you must
initialise this pointer to DoubleBufferPacket. This makes
it possible for the GEL software to easily display the
bobs in both bitmaps, without any extra work (chip mem).
BUserStuff BUserExt;
Here you, the user, can add your own extensions to the bob
structure. Simply used #define BUserStuff to define the
type of extension in your program. This extension can then
be accessed either by the AnimCRoutines, AnimORoutines or
a collision routine. When you don't define BUserStuff, it is
automatically defined as a SHORT variable.
The bob structure defines the bob (blitter object). Bobs can be as large as
you want and can contain as many colours as the RastPort in which they are
used.
PAGE 510
-----------------------------------------------------------------------------
struct ColorMap
You use this structure to set the colours for a ViewPort. To change them
afterwards use LoadRGB4(), getRGB4() and SetRGB4().
--------------------------------------------
struct Custom
This structure provides a picture of the hardware registers which helps
you effictively access them with C. The Appendix for the hardware registers
describes all the symbol registers for this structure and how to use them
(chip memory).
--------------------------------------------
struct DBuffPacket
This structure was designed for using bobs in double buffered bitmaps.
The backgrounds from both bitmaps, which are selected by you, are saved
here when the bob is drawn over them. When you set the SAVEBACK flag in
the vsprite structure the background is saved from only one of four
bitmaps. By installing a DBuffPacket(Bob.DBuffer = &DBuffPacket) for every
bob, you can also save the background of the second bitmap. However, a
DBuffPacket cannot be generated for only one bob in a GEL list. Either
all or none of the bobs in the GEL list have a DBuffPacket.
You must also provide the DBuffPacket structure and the address of an
additional memory area in chip memory (DBuffPacket.BufBuffer = &Memory).
This area must be the same size as the Bob.SaveBuffer. The other
variables for DBuffPackets are handled by the GEL software.
--------------------------------------------
struct GfxBase
GfxBase is your pointer to the graphic function library. You initialise
this library with GfxBase = OpenLibrary("graphics.library",VERSION_NUMBER).
Now you have access to all the graphic functions that the Amiga has
available.
Also, GfxBase contains a pointer to the currently active View. When you
use a program that creates its own View, without intuition, you should
save the current View. By using OldView = GfxBase->ActiView you can
save this pointer, return the intuition View and, thereby, thw workbench
screen.
Another GfxBase structure variable, GfxBase->SpriteReserved provides
information on the hardware sprites that are currently available for use.
PAGE 511
-----------------------------------------------------------------------------
There are a few more pointer in GfxBase such as the SystemFont list etc..
that are exclusively for system use. These pointer can also be affected
by the Graphic functions.
--------------------------------------------
struct GelsInfo
{
BYTE sprRsrvd;
This variable provides information about the sprites
available to the vsprite generator. When your program does
not require the hardware sprites simply set all the bits
in sprRsrvd. This tells the Amiga to use all the hardware
sprites as vsprites. If you want to use both hardware
sprites and vsprites, you must ensure that your hardware
sprites are not used as vsprites. To accomplish this, clear
the corresponding bit in SprRsrvd (bit 0 for sprite 0 and
bit 1 for sprite 1 etc..).
UBYTE Flags;
These variables are used only by the system.
struct VSprite *gelHead, *GelTail;
The GELs (vsprites and bobs) are organised in a GEL list.
These two pointers point to the beginning and end of this
list and are initialised with InitGels().
WORD *nextLine;
This pointer points to a memory area that is eight words
long. It contains information on the highest vertical
positions at which a hardware sprite can be displayed
by using the vsprite software.
WORD **lastColor;
This eight pointer array helps the copper. It stores the
address of the last color definition that was saved for the
hardware sprites. This address is compared to the colour
table address for the new sprite that will be displayed.
If they are the same, a color change is not performed by the
Copper because these colours have already been displayed.
When all eight pointers point to the same vsprite color
table you can display up to eight vsprites in one raster
row instead of only four.
struct collTable *collHandler;
This is where you store the various addresses for collision
routines using SetCollision(). Whether or not these are
called depends on which GELs collide with which collision
masks (MeMask and HitMask).
short leftmost, rightmost, topmost, bottommost;
These four variables are used to set the rectangle
boundaries within which your GELs are confined without
having a Border_Collision. When you GEL exceeds these
boundaries, collision routine zero is called. In order for
this to function you must set bit zero in the GELs BitMask.
PAGE 512
-----------------------------------------------------------------------------
APTR firstBlissObj.lastBlissObj;
These two pointers are only used by the operating system.
}
The GElsInfo structure contains very important variables and pointers for
the GELs (graphic elements). It must be initialised with InitGels() before
the GEL routines (AddBob(), AddVsprite(), Animate(), AddAnimOb()) can be
used. This structure must be passed to the initialised RastPort (RastPort.
GElsInfo = &GelsInfo).
--------------------------------------------
struct IntuiMessage
This structure allows you to intercept and check messages received by
Intuition, such as those from a window. With their help you can determine
whether or not a menu item has been selected, the mouse has moved or a
mouse button has been pressed.
--------------------------------------------
struct IntuitionBase
Just as any library, the intuition library also has a BasePointer.
This base pointer is used in the same way as the starting address for
accessing the library functions.
--------------------------------------------
struct NewWindow
{
SHORT LeftEdge, TopEdge;
SHORT Width, Height;
These four variables determine the position of a window.
(LeftEdge (X coordinate), TopEdge (Y coordinate)), width
and height.
UBYTE DetailPen, BlockPen;
These two variables are used to set the color for your
BlockPen and the Title. The values you use here are the
same ones used for SetAPen() (the number of the colour
register).
ULONG IDCMPFlags;
The IDCMP flags (Intuition Direct Communication Message
Ports) determine the type of communication between the user
and Intuition. You can decide what messages are sent, by
Intuition to your program. You may also want to receive
messages for a mouseclick (MOUSEBUTTON) or a key press
(RAWKEY / VANILLAKEY). Unfortunately, we do not have
enough room here to provide a complete listing of all the
IDCMPs.
PAGE 513
-----------------------------------------------------------------------------
ULONG Flags;
By using these flags it is possible to describe a window
in more detail. For example, you can set BORDERLESS so
the window has no border. With ACTIVATE, a window can be
active as soon as you open it and will immediately become
the input/output window. Again, a complete list of all the
possibilities is not possible here.
struct Gadget *FirstGadget;
This pointer points to the first gadget you have created.
Gadgets are similar to the small boxes seen in the upper
right corner of system windows, which place the window in
the background when they are clicked.
struct Image *CheckMark;
This pointer points to the Image structure used for the
checkmark, which is used to show static menu items. By
entering a zero here you can use the default checkmark.
UBYTE *Title;
When you want to use several windows it is easier to give
each one a name or title. This name is displayed in the top
row of the window. Title is the pointer to the first
character of your title string (for example, the system
window is named AmigaDOS).
struct Screen *Screen;
In order for a window to exist, it needs a screen. A window
must be displayed at some time. This pointer points to an
opened screen where the window is later displayed.
struct BitMap *BitMap;
When you have set the SUPER_BITMAP flag in the flags
variables, this pointer must point to the bitmap you have
created. It is possible to create a bitmap with 1024*1024
pixels and display part of it as large as the window on
your screen.
SHORT MinWidth, MinHeight;
SHORT MaxWidth, MaxHeight;
Once you have set the WINDOWSIZING flag in the flags
variables (and also set SIZEBRIGHT (Size Border Right) or
SIZEBOTTOM (Size Border Bottom) the window sizing gadget
will appear. This gadget, located in the bottom right
corner of your window, allows you to change the size of
your window. You can set the sizing limits by using the
variables MinHeight, MinWidth, MaxHeight and MaxWidth.
PAGE 514
-----------------------------------------------------------------------------
USHORT Type;
This variable lets you determine whether or not this window
will appear in the Workbench area (WBENCHSCREEN). Here you
must set the screen structure pointer to zero otherwise the
window will appear in its own screen (CUSTOMSCREEN). You
must also provide the NewWindow structure with an address
for the screen where the window should appear.
}
These structures let you describe a window. After setting all the pointers
and variables, call Window = OpenWindow (&NewWindow). As an example, you
can now use your window for graphic output.
--------------------------------------------
struct NewScreen
{
SHORT LeftEdge, TopEdge, Width, Height, Depth;
These variables allow you to set the position, size and
depth (number of bitplanes) for your screen. While doing
this, you must also ensure that your window cannot be
moved horizontally (in the X direction). Otherwise, values
for LeftEdge that are not equal to zero will have the same
effect as if they were equal to zero.
UBYTE DetailPen, BlockPen;
The colour for text (DetailPen) and title (BlockPen) for
the top screen row are also set here in the same way as
windows.
USHORT ViewModes;
In this variable you can set the display resolution mode
for your screen.
USHORT Type;
This variable sets the type of screen and must always be
specified as CUSTOMSCREEN. When you initialise your own
bitmap you also have to set the CUSTOMBITMAP flag.
struct TextAttr *Font;
If you want to use a different font with your screen you
can select it here. Simply define a TextAttr structure
describing the new font and provide the address. This
screen and any windows within it will use the selected
font. To use the default font (Topaz) set this variable
to zero.
UBYTE *DefaultTitle;
As with windows, this pointer points to a title text
string for the top screen row of your screen. (The
Workbench screen has the title "Workbench screen"). If you
do not want a title set this pointer to zero.
PAGE 515
-----------------------------------------------------------------------------
struct Gadget *Gadgets;
Currently this pointer is not used and should be set to
zero for guaranteed upward compatibility.
struct BitMap *CustomeBitMap;
This pointer points to your bit-map when Type is set to
CUSTOMBITMAP.
}
The NEWSCREEN structure is used to describe a screen. It is opened with
Screen = OpenScreen (&NewScreen).
--------------------------------------------
struct RastPort
{
struct Layer *Layer;
This pointer points to the Layer structure of the
RastPort. Layers are data structures that help manage
windows. They prevent a window from overwriting another
by mistake.
struct BitMap *BitMap;
This is the pointer to the BitMap used by the RastPort. For
screens other than Intuiton this must be initialised later.
USHORT *AreaPtrn;
This pointer points to the fill pattern of the RastPort.
Normally an area is filled without any special pattern, but
by using the macro SetAfPt() you can change the fill pattern.
struct TmpRas *TmpRas;
This pointer points to an additional memory area that is
used for the fill functions Area...() and Flood. This area
must be large enough to store the entire area that is being
filled.
struct AreaInfo *AreaInfo;
This pointer is only used by the Area().. commands. The
points for a polygon set by AreaDraw() and AreaMove()
must be stored in some location. Use InitArea() to
initialise an AreaInfo structure that contains sufficient
memory (five bytes per coordinate). Then link this structure
to the RastPort for get AREA(RastPort.AreaInfo =
&AreaInfo).
struct GelsInfo *GelsInfo;
This structure is used to display vsprites and bobs in a
RastPort. It contains a linked list of all the graphic
elements for Vsprites. You can sort and display this list
by using SortGList() and DrawGList().
PAGE 516
-----------------------------------------------------------------------------
UBYTE Mask;
This variable contains information about which bitplanes
of a RastPort are affected by a graphic operation. The
normal value is 0xff which means all bitplanes are affected
(each set bit represents an on bitplane). You can change
this variable as required with SetWrMsk(&RastPort, Mask)
BYTE FgPen;
This variable contains the number of the color register
that is responsible for setting the APen colour. FGPen ==
APen, the APen was previously named ForegroundPen.
BYTE BgPen;
BgPen == BPen. (Bpen was the BackgroundPen).
BYTE AOIPen;
AOIPen (Area Outline Pen) == Open
BYTE DrawMode;
This variable contains the actual drawing mode set by the
macro SetDrMd().
BYTE AreaPtSz;
This variable contains the number of rows that are in the
fill pattern. This can always be changed by using SetAfPt(),
but remember that the height must be set in powers of two.
BYTE linpatent;
This help variable is used for drawing lines.
BYTE dummy;
USHORT Flags;
These variables contain various flags. For example, they
can determine whether the first pixel of a line is drawn
(FLAGS \= FRST_DOT) or if only one pixel per raster row
is drawn (ONE_DOT). Another example is whether Area..()
frames an area with the color of the OPen (Flags \=
AREAOUTLINE).
USHORT LinePtrn;
This variable contains the 16 bit line pattern that can be
set with the macro SetDrPt().
SHORT cp_x, cp_y;
These two variables contain the X and Y position of the
graphic cursor, which you can position within the bitmap
with the Move() Command.
UBYTE minterms[8];
We do not have much information for this and the following
two variables. The reason for this is that these parameters
dont provide any visible results when they are changed.
PAGE 517
-----------------------------------------------------------------------------
SHORT PenWidth, /* See minterms */
SHORT PenHeight, /* See minterms */
struct TextFont *Font;
This pointer points to the TextFont structure for the font
currently in use. When the normal font "topaz.font"
becomes tiresome you can change fonts by using OpenFont()
and SetFont().
UBYTE AlgoStyle;
This text contains the text style that you set with
SetSoftStyle().
UBYTE TxFlags;
This variable contains the flags that define your font in
detail for the RastPorts. Here you can determine whether
a font supports proportional characters (TxFlags ==
FPF_PROPORTIONAL), is loaded from RAM (FPF_ROMFONT) or
from disk (FPF_DISKFONT).
UWORD TxHeight;
This variable provides the character height of the current
RastPort font.
UWORD TxWidth;
This is the average width of the individual characters.
UWORD TxBaseline;
This variable contains the position of the baseline for the
font. With the style FPF_UNDERLINED the baseline is drawn
in with each character for underlining. The most important
aspect of the baseline is text positioning with Text().
Strings are not positioned by using a Y position for the
top line of the text. The string is positioned by a Y
position of the graphic cursor and the baseline.
WORD TxSpacing;
This variable sets the pixel width for each character (the
width of a character). This apllies to the display of single
characters but not strings.
APTR *RP_User;
This variable is reserved for the user. You can use this
variable, for example, to link your own data structures with
the RastPort for special purposes.
PAGE 518
-----------------------------------------------------------------------------
UWORD wordreserved[7]; /* reserved */
ULONG longreserved[2]; /* reserved */
UBYTE reserved[8]; /* reserved */
}
When changing a bitmap, The RastPort structure is the most important
structure. Most graphic commands require a RastPort structure because
the actual values of the foreground pen and many other variables are
available
After initialising the RastPort with InitRastPort (&RastPort), simply
initialise the bitmap pointer with RastPort.BitMap = &BitMap.
--------------------------------------------
struct Rasinfo
{
struct RasInfo *Next;
When you have set your ViewPort for DUALPF display mode
(Dual Playfields) you also have to specify two bitmaps that
overlap in the ViewPort. Here you link two RasInfo
structures that point to one of the two BitMaps by using
RasInfo1.Next = &RasInfo2. Then the first of the two
RasInfo structures is made available to the ViewPort with
ViewPort.RasInfo = &RasInfo1;. The rest happens as usual
when opening the View and ViewPorts.
struct BitMap *BitMap;
This is the pointer to the bitmap of the RasInfo structure
that will be displayed in the ViewPort.
SHORT RxOffset, RyOffset;
These two variables determine which pixel of the BitMap
lines up with the upper left corner of the ViewPort. They
are normally set to zero which means that the upper left
corner of the BitMap and the ViewPort line up exactly. By
changing these values and then calculating a new Copper
list you can achieve a scrolling bitmap.
}
The RasInfo structure is the referee between ViewPort and BitMap.
--------------------------------------------
struct Screen
This structure which is similar to the window structure, provides access to
an already opened screen (Screen = OpenScreen(&NewScreen). All system
structures, such as those used for graphic output (Screen->RastPort.xxx,
Screen.ViewPort.xxx etc...), are available to you through this structure.
PAGE 519
-----------------------------------------------------------------------------
struct SimpleSprite
{
UWORD *posctldata;
This pointer points to a memory area in this form;
struct SpriteData
{
UWORD posctl[2];
/* represents the hardware register
'spr[x].pos' and 'spr[x].ctl' )
UWORD Appearance[Height*2];
/* This array contains the appearance of */
/* the sprites row for row defined in */
/* Two UWORDs */
UWORD reserved[2] = {0,0};
}
You must create the spritedata structure yourself because it does
not exist in an include file.
UWORD Height;
This variable contains the height of the sprites. Sprites
are always 16 pixels (1 word) high.
UWORD x,y;
These two variables contain the current position of the
sprites.
UWORD num;
This variable contains the number of the hardware sprites
(0-7) that are described and changed by the SimpleSprite
structure.
}
The SimpleSprite structure permits the use if a hardware sprite. Sprites are
always 15 pixels wide and can be any desired height.
You, as the programmer, must provide the strutures that determine the
appearance of the sprites (SpriteData). Then use SimpleSprite.posctldata =
(UWORD *) &SpriteData to pass this data to the SimpleSprite structure.
--------------------------------------------
struct TextAttr;
{
STRPTR ta_Name;
This pointer points to the name of the font ("name.font")
that you want to open with OpenFont() or OpenDiskFont().
PAGE 520
-----------------------------------------------------------------------------
UWORD ta_YSize;
This is where the height in rows is stored for your font.
UBYTE ta_Style;
You use this variable to set a beginning style for the
font you opened above.
UBYTE ta_Flags;
This variables tells you whether or not your font can use
proportional characters.
This structure is used by the command OpenFont() and OpenDiskFont(). The
variables ta_Name and ta_YSize are used to try to load a specific font and
also find a font that best fits your selected parameters.
--------------------------------------------
struct TextFont
This structure is used to access a font opened with OpenFont() or
OpenDiskFont(). It can be linked to a RastPort with SetFont() or added
to the system font list with AddFont() amd removed with RemFont().
--------------------------------------------
struct TmpRas;
The TmpRas structure is used by the fill commands Flood and Area.. It
must be initialised with InitTmpRas and linked to a RastPort. Now you can
use the Area... and Flood commands with this RastPort.
The TmpRas structure is used to make an area of memory available for use.
It must be large enough to store a bitplane of the largest element you
want filled. This is a requirement of the recursive fill algorithm.
--------------------------------------------
struct View
{
struct ViewPort *ViewPort;
This is the pointer for the first ViewPort of the View.
struct cprlist *LOFCprList;
This is the pointer to the Copper list created with
MrgCop().
struct cprlist *SHFCprList;
This is also a pointer to a copper list, but this list is
only used with interlace mode and is required because
LOFCprList is always used.
PAGE 521
-----------------------------------------------------------------------------
short DyOffset, DxOffset;
These two variables determine the position of your View on
the monitor. They are automatically set by InitView() so
you dont have to worry about the View programming.
UWORD Modes;
This variable contains the resolution mode of the View. In
order to use the interlace mode in any particular View, you
must set it here.
}
The View structure is the manager of graphic displays and provides the most
important link between you and the system.
--------------------------------------------
struct ViewPort
{
struct ViewPort *Next;
Since it is possible to display more than one ViewPort in
a View, this is the pointer to the next ViewPort. The
ViewPorts must also be linked together. After using
InitVPort() this pointer equals zero which means that
there are no other ViewPorts.
struct ColorMap *ColorMap;
This pointer determines the ColorMap of the ViewPort.
Because every ViewPort has its own colormap it is possible to
set different colours for each ViewPort within a View.
struct CopList *DspIns; /* Display instructions */
struct CopList *SprIns; /* Sprite Instructions */
struct CopList *ClrIns; /* Sprite Instructions */
struct CopList *UCopList *UCopIns;
These are the pointers to the intermediate or ViewPort
Copper list created with MakeVPort().
SHORT DWidth, DHeight;
These two variables determine the height and width of the
ViewPort in pixels. For example, the number of lines used
for this ViewPorts resolution (hi-res or lace).
SHORT DxOffset, DyOffset;
These two variables determine the position of the ViewPort
within the View. InitVPort() sets these equal to zero, so
you will have to change them.
UWORD Modes;
This is where you set the resolution mode of the ViewPort.
You are not limited in choice since HAM, Extra Halfbrite,
sprites and all the modes are available. Remember to always
use the highest resolution mode that you will be using in
your View.
UWORD reserved;
struct RasInfo *RasInfo;
This pointer makes the link between ViewPort and bitmap
through the RasInfo structure.
}
The ViewPort that is described by the ViewPort structure is the window
through which you can see your bitmap on the monitor.
PAGE 522
-----------------------------------------------------------------------------
struct VSprite
{
struct VSprite *NextVSprite;
struct VSPrite *PrevVSprite;
These two pointers are used to create the GEL list which is
sorted using SortGList() by X and Y values (See below for
display).
struct VSprite *DrawPath;
struct VSprite *ClearPath;
These pointers are used to display the bobs in an organised
manner. DrawPath writes the bobs into the RastPort.
ClearPath is calculated from DrawPath and, as desired,
removes the bobs from the RastPort and restores the
background.
WORD OldY, OldX;
These two pointers are used to restore the background
covered by a bob when a bob moves. By setting the SAVEBACK
flag in the the VSprite structure for a bob and defining a
memory buffer area, you can save the background that is
hidden when a bob is displayed. When you move the bob and
call DrawGList(), the old background is displayed again. The
old bob position is stored in OldX and OldY so the computer
knows where to restore the background.
WORD Flags;
This variable determines how the system handles the Vsprite.
When the VSprite structure is being used to display
vsprites then Flags = VSPRITE. However, bobs also use this
structure.
WORD Y,X;
These two variables determine the position of the VSPRITE
or bob on the screen.
PAGE 523
-----------------------------------------------------------------------------
WORD Height;
This variable sets the number of vertical rows for a
vsprite or Bob.
WORD Width;
This variable determines how many words are used to display
one row of a bob. A value of one is used for width when
using vsprites because they cannot be wider than 16 pixels
( = 16 bits = 1 word).
WORD Depth;
This is where you set the bitplanes for the bob. This is
actually how many bitplanes you have defined for the bob.
Please note that your bob cannot have a depth greater than
the RastPort in which it is used. However, a bob can have
less bitplanes than the RastPort.
WORD MeMask;
WORD HitMask;
You use these two variables to determine which collision
routine (if any) is executed upon a collision with another
GEL. The MeMask of one and the hitmask of the other GEL
are ANDed and the result bit determines which collision
routine is used. (bit 1=> routine 1, bit2 => routine2, ...
bit 15 => routine 15).
When you set bit zero in HitMask , a GEL border collision
calls routine zero.
WORD *ImageData;
This pointer points to the bob/vsprite data that determine
their appearance. This data must be stored in chip memory.
WORD *BorderLine;
WORD *CollMask;
These two pointers point to memory buffer areas, defined by
you, for the BorderLine and CollisionMask. They are also
used to detect collisions.
The Borderline contains as many words as the width of a
bob or vsprite (vsprites are always one word wide).
Borderline os a logical OR of all the GEL rows. The ColMask
is exactly the same size as your GEL, but is only one
bitplane deep. ColMask contains a logical OR of all plane
data. (Both of these buffers must be created by you and are
initialised with InitMasks(). They must also be located in
chip memory.
WORD *SprColors;
This pointer points to a three UWORD memory area that
contains the VSprite colors.
PAGE 524
-----------------------------------------------------------------------------
struct Bob *VSBob;
If you dont set the VSprite.Flag in the VSprite.Flags
variables, the system assumes that your vsprite structure
is being used to describe a bob. This pointer points to the
bob structure of the vsprite.
BYTE PlanePick;
BYTE PlaneOnOff;
These two variables determine which bit-planes are on
(PlanePick) for displaying your bobs and which are passive
and written with the Bobs ImageShadow.
VUserStuff VUserExt;
With the help of this "extension", the user can combine
his own data into the vsprite. The VUserStuff function
can be defined at any point before the #include statements
are executed (e.g. #define VUserStuff struct Speed (vx,vy);
}
The vsprite structure is needed for both types of GELs. Both the vsprite
itself and the bob are applications of this structure.
--------------------------------------------
struct Window
When you open a new window using WINDOW = OpenWindow(NewWindow), you can
write in the window, bypassing the window structure. This is because you
have a RastPort available (Window->RastPort).
In addition, you can get the window information from Intuition. However,
a detailed description of this will go far beyond the scope of this
Appendix.
PAGE 525
-----------------------------------------------------------------------------
APPENDIX B - THE LIBRARY FUNCTIONS
This appendix provides the C programmer with information about the
library routines used in this book.
First you must open the required libaries (with Openibrary()) before you
can use the library routines.
We have organised the following routine listing by library and in
alphabetical order.
GFXBASE: First the GfxBase routines :
------------------------------------------------------------------
AddAnimOb(&AnimOb, &AnimKey, &RastPort)
These routines are used to organise, in the GEL list of a specific
RastPort, all the bobs for the animation object. This makes it
possible for DrawGList() to draw the bobs in an orderly manner.
The AnimKey points to the last added AnimOb. AnimKey must be equal
to zero for the first AddAnimOb() call (struct AnimOb*AnimKey = 0).
------------------------------------------------------------------
AddBob(&Bob,&RastPort)
This routine adds the specified bob structure for the defined bob
(Blitter object) to the GEL list for the selected RastPort. You
must do this so the bob can later be drawn with DrawGList().
See: AddVSprite(), DrawGList(), SortGList(), InitGList()
------------------------------------------------------------------
AddFont(&TextFont)
This function links the specified TextFont structurem which defines
your font, with the SystemFontList.
Once this is done, your font is available to any program you are
using.
PAGE 527
-----------------------------------------------------------------------------
AddVSprite(&VSprite,&RastPort)
This routine adds the specified vsprite structure, which defines
your vsprite (virtual sprite), to the GEL list of the selected
RastPort. This is needed so that DrawGList() can later display
your Vsprite.
See: AddBob(), DrawGList(), SortGList(), InitGList()
------------------------------------------------------------------
Pointer = AllocRaster(Width, Height)
This function enables you to allocate a memory area for a bitplane
in a size specified by the width and height. After calling this
routine, the first word of the memory address is returned in
pointer.
See: FreeRaster()
------------------------------------------------------------------
Animate(&AnimOb,&RastPort)
This routine applies to all animation objects that are linked to
an AnimOb. Animate calculates the new object positions and resets
Timer for the animation components. In a ring animation
(AnimComp.Flags = RINGTRIGGER), when Timer for a component is equal
to zero the next sequence is activated.
See: AddAnimOb()
------------------------------------------------------------------
AreaDraw(&RastPort,x,y)
This function adds a polygon to the AreaInfo structure for the
specified RastPort. X and Y determine the coordinates of this
point in the BitMap.
See: AreaMove(), AreaEnd(), InitArea()
PAGE 528
-----------------------------------------------------------------------------
AreaEnd (&RastPort)
This function executes the drawing of a polygon, which is defined
with AreaMove() and AreaDraw(). It also fills the polygons with the
current fill pattern controlled by the current APens, BPens, OPens
and Draw modes.
The APen and BPen determine the color of the fill pattern. The
OPen sets the framing colour for the polygon.
Remember that you must first initialise an Area and TmpRas structure
in the RastPort where the polygon will be drawn. Unless you do
this first, filling an area using the Area... function will not
function.
See: AreaDraw(), AreaMove(), InitArea(), InitTmpRas.
------------------------------------------------------------------
error = AreaEllipse(&RastPort, XMiddle, YMiddle, XRadius, YRadius)
This function allows you to draw an ellipse in the selected RastPort.
The centre is at XMiddle,YMiddle. XRaduis and YRadius set the
radius for the ellipse. (When XRadius = YRadius a filled circle
is drawn. Remember that XRadius and YRadius must be greater than
zero).
AreaEllipse is an expansion of the Area.. function. This means that
a filled ellipse is drawn using the current fill pattern.. It also
means that an AreaInfo amd TmpRas structure must exist in the
selected RastPort.
The variable ERROR provides information about the vector table,
which contains the coordinates for the polygon plot points in
AreaInfo. It tells you whether or not there is enough room
(minimal (2+1)*5 bytes) for the data required for an ellipse
(error = 0). If ERROR returns a -1 there isnt enough room.
You must call AreaEnd() to execute the drawing of the ellipse.
See: AreaDraw(), AreaEnd(), AreaMove(), InitArea(), InitTmpRas.
PAGE 529
----------------------------------------------------------------------------
AreaMove(&RastPort,x,y)
AFter building your polygon with AreaDraw(), close it with this routine.
Any additional AreaDraw() functions will start a new polygon with the
above coordinates.
See: AreaDRaw(), AreaEnd(), InitArea()
------------------------------------------------------------------
AskFont(&RastPort, &TextAttr)
This function initialises, in the selected RastPort, the specified
TextAttr structure with the values of the current font. You can
use this function to check the RastPort for the currently active
font.
See: SetFont()
------------------------------------------------------------------
Style = AskSoftStyle(&RastPort)
This function moves, into the selected RastPort, all the possible
font styles that can be set with AskSoftStyle. Each set bit in
style represents a font style:
FSF_UNDERLINED = Bit 0 = 1 (Underlined)
FSF_BOLD = Bit 1 = 2 (Bold)
FSF_ITALIC = Bit 2 = 4 (Italic)
FSF_NORMAL = No set bit = 0
See: SetSoftStyle()
------------------------------------------------------------------
BitPlanes = BltBitMap(&SourceBitMap,X1,Y1,&TargetBitMap,X2,Y2,Width,
Height,Minterm,Mask,Buffer).
This function blitters a rectangle from one bitmap into another
bitmap. You must specify the source rectangle coordinates from the
SourceBitMap(X1,Y1) and the position for the rectangle in the
TargetBitMap(X2,Y2). Since the width and the height are the same for
both rectangles, they are set only once. You must reference both the
source and target bitmaps. Remember that these can also be references
within the same bitmap.
PAGE 530
-----------------------------------------------------------------------------
You also specify the minterm which determines how the source and
target rectangles are logically mixed. What the minterms do and
which ones exist is discussed in Chapter 16.
The Mask parameter determines which bitplanes are blittered. The
default value is $ff which means that all bitplanes are referenced.
You can also filter out specific bitplanes by clearing the
corresponding bit (bit zero for bitplane zero etc.).
Buffer points to a memory area that is used when a target and source
rectangle overlap in the same bitmap. This buffer must have enough
memory to store one row of the rectangle. When you are sure that the
two rectangles do not overlap, you can set the pointer to zero.
The result returned by this function is from the "Blit" affected
bitplanes (see Mask).
Remember that this routine doesnt test whether the target
rectangle fits completely within the target bitmap. It is possible
to blitter over the edge of a bitmap. This can cause errors which
results in less bitplanes being affected than expected. With
extreme error conditions you will encounter the familiar Guru
Meditation.
See: ClipBlit()
------------------------------------------------------------------
BltBitMapRastPort(&SourceBitMap,X1,Y1,&TargetRastPort,X2,Y2,Width,
Height,Minterm)
This function performs exactly the same operation as BltBitMap().
This time you are moving a rectangle from a bitmap into a
RastPort.
The Mask and Buffer parameters are not required here.
THe result returned by this function is TRUE = successful,
FALSE = error.
See: BltBitMap()
------------------------------------------------------------------
BltClear(&Memory, NumBytes, Flags)
As the name indicates, this function erases a selected memory area.
You simply specify the starting address.
The flag parameter determines how the NumBytes value is interpreted:
PAGE 531
-----------------------------------------------------------------------------
With bit one of the flag parameter set to 1:
The upper 16 bits of NumBytes is the number of lines to erase.
The lower 16 bits of NumBytes is the number of bytes per line
to erase.
Width bit one set to zero NumBytes represents the actual number of
bytes to erase.
Bit zero of the flags parameter determines whether the function is
immediately return to the program or wait until the blitter has
erased everything.
------------------------------------------------------------------
BltTemplate(&Source, BitPosition, Modulo, &RastPort, X, Y, Width,
Height)
This function uses the blitter to transfer data from a packed
array into a RastPort. You provide the address of the packed
array and the bit position within this array, where the data
read should start.
Modulo specifies the number of bytes for one row in the data array.
X,Y, width and height set where and how much data from the array is
moved to the RastPort.
------------------------------------------------------------------
ChangeSprite(&ViewPort,&Sprite,&SpriteData)
This function changes the appearance of the specified hardware
sprites. Remember that the hardware sprite must be initialised
already. This ensures that the height and screen position are already
set and that the correct hardware sprite (SimpleSprite.num) is
affected.
The data used by this function have the following format:
struct SpriteData
{
UWORD posctl[2];
UWORD Data[Height][2];
UWORD Reserved[2]; /* = 0,0 */
}
posctl represents the sprite hardware register spr[x].pos and
spr[x].ctl. This allows the user to use GetSprite() to reserve both
the even and odd numbered sprites and set the SPRITE_ATTACHED bit in
posctl[l] for attached sprites. When the bit pattern of both sprites
overlap, they are merged. This permits the use of 15 colors instead
of only three (plus transparent).
See: GetSprite(), FreeSprite(), MoveSprite()
PAGE 532
-----------------------------------------------------------------------------
ClearEOL(&RastPort)
This function deletes one row, in the selected RastPort, that has
the height of the character in the current font. This deletion
starts at the current graphic cursor position (RastPort.cp_x,
RastPort.cp_y).
See: ClearScreen(), Move()
------------------------------------------------------------------
ClearScreen(&RastPort)
In contrast to the ClearEOL() function, which only clears one row,
ClearScreen deletes the entire RastPort from the current graphic
cursor position.
See: ClearEOL(), Move()
------------------------------------------------------------------
ClipBlit(&SourceRastPort,X1,Y1,&TargetRastPort,X2,Y2,Width,Height,
Minterm)
This function performs exactly the same function as BltBitMap().
Most of the parameters have the same meaning. But with this function
we blit from one RastPort to another and any overlapping problems
are handled by the routine.
This function is much better because it is easy to use (you do not
have to reserve a buffer) and it prevents you from creating any
error conditions. Blitting over the border of a RastPort does not
create the problems possible with BltBitMap().
See: BltBitMap(), BltBitMapRastPort()
------------------------------------------------------------------
CloseFont(&TextFont)
When you have opened a font with OpenFont() or OpenDiskFont() you
must also close it again before ending your program. Otherwise the
memory used by your font is not released back to the system.
See: OpenFont()
PAGE 533
-----------------------------------------------------------------------------
DisownBlitter()
This function releases the blitter from your control and allows
other programs to use it again.
See: OwnBlitter()
------------------------------------------------------------------
DoCollision(&RastPort)
This routine tests all GELs in the GEL list for a RastPort, for
collisions and also executes any collision routines you have set up
with SetCollision().
However, we must inform you that DoCollision() does not function all
the time.
See: SetCollision.
------------------------------------------------------------------
Draw(&RastPort,x,y)
This is one of the most important graphic functions. DRAW allows
you to draw a line from the current graphic cursor position to the
selected X/Y coordinate in the specified RastPort.
See: Move()
------------------------------------------------------------------
DrawEllipse(&RastPort, XMiddle, YMiddle, XRadius, YRadius)
This function allows you to draw ellipses or, with XRadius =
YRadius, circles. These are not filled as with AreaEllipse; only
the outline is drawn.
Remember that XRadius and YRadius must contain values that are
greater than zero.
PAGE 534
-----------------------------------------------------------------------------
DrawGList(&RastPort,&ViewPort)
DrawGList() performs two functions. First it can draw the bobs, from
the GEL list in the selected RastPort. Second, it can link the
vsprites, from the ViewPort copper list, with the Selected ViewPort.
However, vsprites are not drawn after calling DrawGList(). First
you have to use MakeVPort() or MakeScreen() to set up the new Copper
list. Then you use MrgCop() and LoadView() or RethinkDisplay to
display them.
See: MakeVPort(), MrgCop(), LoadView(), MakeScreen(),
RethinkDisplay()
------------------------------------------------------------------
Flood(&RastPort, Mode, x, y)
This function enables you to fill an area in a RastPort. All the
pixels around the area from the specified X/Y positions are tested
and filled according to the mode selected. Mode = 0 tests for the
colour of the Open and mode=1 tests for the color of the starting
pixel.
Any pixels around your starting point that dont meet the
requirements of either mode are filled with the current fill
pattern. When the pixel meets one of the mode criteria it is not
changed.
When all pixels within a closed border meet the mode criteria and
are already filled, the fill is cancelled.
Remember that for the Flood() function a TmpRas structure must be
initialised and must have enough memory to be used by the Flood()
function.
See: InitTmpRas()
------------------------------------------------------------------
FreeColorMap(&ColorMap)
You use this function to release the memory, which was reserved
through GetColorMap() for the ColorMap structure, back to the
system.
See: GetColorMap()
PAGE 535
-----------------------------------------------------------------------------
FreeCopList(&CopList)
Call this routine in order to release a single intermediate Copper
list for a ViewPort (struct CopList), which was created by using
MakeVPort(). FreeVPortCopList() uses this routine to release all
intermediate lists from a ViewPort.
See: FreeVPortCopList()
------------------------------------------------------------------
FreeCprList(&cprlist)
Use this function to release the memory reserved, through
View.LOFCprList and View.SHFCprList, for the hardware Copper list.
These hardware copper lists are calculated from the individual
ViewPort Copper lists by using MrgCop().
See: MrgCop()
------------------------------------------------------------------
FreeRaster(&BitPlane, Width, Height)
This function produces the opposite effect of AllocRaster(). It
releases all reserved bitplane memory, that was allocated with
AllocRaster(), back to the system. This makes the memory available
to other programs again.
BitPlane points to the memory area that you reserved with
AllocRaster. Width and Height must be the same for free and
AllocRaster(), otherwise it is possible to release too much or too
little memory.
See: AllocRaster()
------------------------------------------------------------------
FreeSprite(SprNumber)
With FreeSprite you can release a sprite, that was reserved
specifically for your through GetSprite() back to the system.
This makes the sprite available again for full system use
(especially the vsprites).
You just provide the number of the sprite that was reserved with
GetSprite().
PAGE 536
----------------------------------------------------------------------------
See: GetSprite(), ChangeSprite(), MoveSprite()
------------------------------------------------------------------
FreeVPortCopLists(&ViewPort)
With this function you can release, for the specified ViewPort that
you generated with MakeVPort(), all the Copper lists for the
colour, display, sprites etc...
See: MakeVPort(), FreeCopList()
------------------------------------------------------------------
*ColorMap = GetColorMap(NumberColors)
This function create a complete ColorMap structure. All of the
required ColorMap structure variables are initialised and enough
memory is reserved for the specified NumberColors. When sufficient
memory is not available for the new ColorMap structure or color
buffer, a ZERO(0) is returned by the routine.
You must link this ColorMap structure to the ViewPort with
ViewPort.ColorMap = ColorMap(before using MakeVPort() to calculate
the Copper list for the ViewPort).
See: FreeColorMap(), LoadRGB4(), GetRGB4(), SetRGB4()
------------------------------------------------------------------
Color = GetRGB4(&ColorMap,ColorRegister)
This function enables you to retrieve the UWORD that determines
the color of the selected color register. The 16 bit UWORD
which is returned is divided as follows: bits 0-3 are the blue
component, bits 4-7 the green and bits 8-11 red.
See: SetRGB4(), LoadRGB4()
------------------------------------------------------------------
SprNumber = GetSprite(&SimpleSprite,getSprNumber)
This function allows you to reserve any hardware sprite for your
personal use. You provide the SimpleSprite structure, that the
sprite will be associated with, to the function. Also, select the
desired number (0-7) (if it doesnt matter a -1) of the reserved
sprite.
The number of the reserved is returned is returned in the
SpriteNumber. If the selected sprite is not available, SpriteNumber
contains a -1.
See: FreeSprite(), MoveSprite(), FreeSprite()
PAGE 537
-----------------------------------------------------------------------------
InitArea(&AreaInfo,&Buffer,NumCoord)
This function initialises the selected AreaInfo structure for you.
The structure contains the specified Buffer and the NumCoord+1
coordinates required for AreaDraw() and AreaMove(). The buffer
should contain at least five time the number of bytes that are
required for the polygon coordinates which are used with AreaMove()
and AreaDraw().
Declaring the buffer as a char array is the easiest method. Since
programs created with the compiler automatically releases arrays,
you dont have to release the used buffer area again.
See: AreaDraw(), AreaMove(), AreaEnd()
------------------------------------------------------------------
InitBitMap(&BitMap, Depth, Width, Height)
This routine initialises the specified BitMap structures. The
depth (number of bitplanes), width (in pixels), and the height
(in rows) is easily set.
See: AllocRaster()
------------------------------------------------------------------
InitGels(&Begin, &End, &GelsInfo)
This function initialises the selected GelsInfo structure. You need
this structure in order to display vsprites and bobs in an organised
manner.
All the graphic elements (=GEL) are linked in a list through the
vsprite structures (&Begin, &End). &Begin and &End mark the
beginning and end of this GEL list.
After you have used InitGels() to initialise the GelsInfo structure,
then simply make them available to your RastPort (RastPort.GelsInfo =
&GelsInfo). Once this is accomplished, you can start displaying
your bobs and vsprites.
See: AddVSprite, AddBob()
PAGE 538
-----------------------------------------------------------------------------
InitMasks(&VSprite)
You initialise the BorderLine and CollMask for the specified
vsprite structure with this routine. The memory buffer for both
masks must be reserved already and stored in the variables
VSprite.BorderLine and VSprite.CollMask.
------------------------------------------------------------------
InitRastPort (&RastPort)
You use this routine to initialise the specified RastPort
structure. This RastPort structure is the most important connection
between the user and BitMap.
The RastPort contains, for example, the color of the current
foregroundpen(APen). It also contains a pointer to the bitmap
where the graphic functions will be executed and many other
important variables and pointers used by the graphic functions.
------------------------------------------------------------------
TmpRas = InitTmpRas(&TmpRas,&Buffer,BufferSize)
When you use the Area...() functions within a RastPort, an extra
memory area is required for these functions. This buffer must be
at least as large as the object being filled. Because of the
recursive algorithm used by fill, extra memory is required as
workspace.
This buffer only requires one bitplane which is as large as the
largest element. To ensure that you have enough, it is best to
reserve one complete bitplane for the temporary raster.
Now simply pass the initialised TmpRas structure to your RastPort.
There are two possible ways to do this. You can either use the
result returned by the initialised TmpRas structure (RastPort.
TmpRas= InitTmpRas (....)) or pass the initialised TmpRas structure
yourself (RastPort.TmpRas = &TmpRas).
PAGE 539
-----------------------------------------------------------------------------
InitView(&View)
This function is used to initialise the specified View structure.
All variables and pointers for the View structure are first set
to zero. Then the DxOffset and DyOffset variables are set so that
the View is positioned approximately two centimetres below the top
right monitor border. This assumes that the monitor is properly
adjusted.
See: MrgCop(), MakeVPort()
------------------------------------------------------------------
InitVPort(&ViewPort)
This function is used to clear all variables and pointers for the
selected ViewPort structure. This is done so that the individual
Copper lists for this ViewPort will be correctly calculated with
MakeVPort(). When a pointer to a ViewPort Copper list is not equal
to zero, MakeVPort() assumes that a ViewPort Copper list exists
and does not calculate a new one.
Undefined Copper lists could be created without this MakeVPort()
feature.
See: MakeVPort()
------------------------------------------------------------------
LoadRGB4(&ViewPort,&Colotpalette[0],Colorentry)
This routine allows you to load new colour values, ColorEntry from
the ColorPalette (UWORD Colorpalette[Colorentry];) into the
ColorMap for the selected windows.
Using this routine is an easy way to change all the colours of a
ViewPort at one time. However, the change is not immediate. First
you have to calculate a new color Copper list for the ViewPort. You
do this with MakeVPort(), MrgCop() and then LoadView(). When using
intuition screns substitute RemakeDisplay() for LoadView().
See: SetRGB4(), GetRGB4()
PAGE 540
-----------------------------------------------------------------------------
LoadView(&View)
After calling this function, the selected View and all ViewPorts
it contains are displayed on the screen. You must first use
MakeVPort() for each ViewPort that will be displayed in the View.
MakeVPort() creates the ViewPort Copper lists that MrgCop() merges
into a single View Copper list.
The View Copper list starting address is written by LoadView() in
the necessary hardware registers (cop11c, cop21c).
See: InitView(), InitVPort(), MakeVPort(), MrgCop()
------------------------------------------------------------------
MakeVPort(&View,&ViewPort)
This routine calculates the intermediate ViewPort Copper lists for
the selected ViewPort of the specified View. For example, there are
ViewPort Copper lists for color display for all colors which are
written through the Copper to the hardware registers. These color
copper lists are calculated from the ViewPort colormap. When the
color list pointer is equal to zero, the default ColorMap is
used to calculate the ViewPort color Copper list.
These lists also contain the various resolution modes for the
ViewPorts (many ViewPorts in one View can have different
resolutions).
See: MrgCop(), FreeVPortCopLists()
------------------------------------------------------------------
Move(&RastPort,X,Y)
You use this function to position the graphic cursor for the
selected RastPort to the specified position (RastPort.cp_x = x;
RastPort.cp_y = y;)
At this position you could print text or draw a line to another
position.
------------------------------------------------------------------
MoveSprite(&ViewPort,&SimpleSprite, X,Y)
This function lets you position the selected hardware sprites within
the selected ViewPort when ViewPort is not equal to zero. Otherwise,
the sprite will be positioned relative to the View.
X and Y specify the new position. Remember that the position values
in hi-res or lace ViewPorts must be multiplied by two so that the
sprite actually moves.
See: ChangeSprite(), GetSprite(), FreeSprite()
PAGE 541
-----------------------------------------------------------------------------
MrgCop&(View)
This function calculates the View hardware Copper list from the
ViewPort Copper lists created with MakeVPort(). Then this list is
used by the hardware(cop11c,cop21c).
Any change to the colortable or the hardware sprite positions
requires a newly calculated copper list. This happens automatically
when the hardware sprites are moved. When changing the colorpalette
with LoadRGB4() you must update the Copper list.
See: MakeVPort(), FreeCprList()
------------------------------------------------------------------
*TextFont = OpenFont(&TextAttr)
This function searches through the SystemFontList for a font
described by the TextAttr structure. When a font cannot be found
to match the named TextAttr structure, a value of zero is returned.
However, when a font is found but has different styles or sizes, a
font that best meets the specifications is selected.
OpenFont() increases user choices when accessing the Systemfonts.
OpenFont() and CloseFont() must maintain a balance in order to
guarantee a clean memory. When a font is no longer required you
can remove it from memory with RemFont().
See: CloseFont(), AddFont(), RemFont(), OpenDiskFont(),
AvailFonts().
------------------------------------------------------------------
OwnBlitter()
This function informs the Blitter that it is only able to work
for you. Other tasks (programs) that are running at the same time
can no longer use the blitter.
After OwnBlitter(), you should use WaitBlit() to allow the Blitter
to complete any current processing.
See: DisownBlitter(), WaitBlit()
PAGE 542
----------------------------------------------------------------------------
PolyDraw(&RastPort.NumCoords, &PixelArray)
This routine enables you to draw into the selected RastPort by
using coordinates from any array you created. Lines are drawn from
pixel to pixel as plotted from the array.
THe pixels are stored in an integer array (int PixelArray
[NumCoords][2]) with each coordinate consisting of two array
elements. The first element is the X and the second is the Y
coordinate for the stored polygon pixels
NumCoords specifies the number of pixels that will be drawn from
the pixel array.
------------------------------------------------------------------
ColorRegister = ReadPixel(&RastPort, X, Y)
This function allows you to read the color value of a specific
pixel at the coordinates you selected.
When your coordinates are outside the selected RastPort, a value
of -1 is returned in ColorRegister.
See: WriteAPen(), SetAPen()
------------------------------------------------------------------
RectFill(&RastPort, X1, Y1, X2, Y2)
With this function you can fill any desired rectangular area within
the selected RastPort. The current fill pattern, Drawmodes, APens,
etc.. affect how your fill is performed.
You just specify the top left corner (X1,Y1) and the lower right
corner (X2,Y2) of the rectangle you want filled. Make sure that
the lower right corner really is lower and to the right of the
upper left corner. When your coordinates are incorrect the computer
can crash because your memory will be filled without the proper
controls.
PAGE 543
-----------------------------------------------------------------------------
This function does not require a TmpRas structure like the Flood()
and Area...() functions.
------------------------------------------------------------------
RemFont(&TextFont)
This function removes the selected font from the system font list.
The font remains available to any programs currently using it.
After all programs signal, with CloseFont(), that this font is no
longer required, the font is pysically removed from memory.
After you have used RemFont() a program that has used CloseFont()
cannot access the font again.
See: AddFont(); OpenFont(); CloseFont()
------------------------------------------------------------------
RemIBob(&Bob, &RastPort, &ViewPort)
This function immediately removes the selected bob from the GEL,
list for in RastPort and deletes it from the RastPort.
See: DrawGList(), SortGList(), InitGels()
------------------------------------------------------------------
RemVSprite(&VSprite)
This routine deletes the selected vsprite from the current GEL
list. However, the sprite does not immediately dissappear from the
screen. This occurs only after the calls to SortGList(), DrawGList(),
MakeVPort(), MrgCop(), LoadView().
See: DrawGList(), SortGList()
------------------------------------------------------------------
ScrollRaster(&RastPort, DeltaX, DeltaY, X1, Y1, X2, Y2)
This function scrolls the rectangle, specified by X1, Y1, X2, Y2
(see RectFill), for DeltaX pixels and DeltaY rows. Positive delta
values scroll up and left. Negative delta values scroll right and
down. Combatting negative and positive 'Delta' values allows you
to scroll in any desired direction.
PAGE 544
-----------------------------------------------------------------------------
The areas uncoverd by the scrolled rectangle are filled with the
color of the BPen.
Please note that this routine is not very fast and can cause some
flickering during the scrolling.
------------------------------------------------------------------
ScrollVPort(&ViewPort)
After you have changed the RxOFfset and RyOffset values in the
RasInfo structure of the ViewPort, use ScrollVPort() to display
a different portion of the bitmap. ScrollVPort calculates the
new copper list for the new bitmap position.
This routine is not fast enough to prevent some flickering on the
screen. Because of this, you should calculate the new Copper list
since this can be performed as a background process.
------------------------------------------------------------------
SetAPen(&RastPort,Colorregister)
This function allows you to select, in the selected RastPort, a new
color for the APen.ColorRegister selected the number of the colour
register in the ViewPort ColorMap.
See: SetBPen()
------------------------------------------------------------------
SetBPen(&RastPort,ColorRegister)
Just like SetAPen, the color of the BPen is changed in the selected
RastPort. Again, ColorRegister specifies the number of the color
register to be used from this point on.
APen and BPen functions differently depending on which drawing mode
you are using. With JAM2 mode, the BPen functions as the background
color pen. For example, text would be highlighted with the BPen.
The BPen has no effect in other draw modes.
See: SetAPen()
PAGE 545
-----------------------------------------------------------------------------
SetCollision(Number, Routine, &GelsInfo)
After comparing the MeMask and HitMask, this function sets the
collisions routines that are used for collisions between GELs or
a GEL with a border.
With GEL to GEL collisions you must pass both vsprite structures to
your collision routine. The first vsprite structure passed
represents the upper left positioned GEL (bob or vsprite).
With border collisions, you pass the involved vsprite structure
and a flag to your routine. The flag contains the code for the
border (TOPHIT, BOTTOMHIT, LEFTHIT, RIGHTHIT) the GEL collided
with.
See: DoCollision()
------------------------------------------------------------------
SetDrMd(&RastPort, Mode)
Use this function to set the DrawMode for your RastPort. This sets
up how lines are drawn, how pixels are set and how text is
displayed. The following modes exist:
JAM1 (0): Only the APen colour is used for drawing.
JAM2 (1): The BPen colour is used for the background.
COMPLEMENT(2): Pixels to be drawn are first XORed with the
existing pixels (by bitplane).
INVERSVID(4) : Pixels are inverted before being drawn (by bitplane).
The modes COMPLEMENT and INVERSVID only function with JAM1 or
JAM2.
------------------------------------------------------------------
SetFont(&RastPort,&Font)
SetFont() makes a font available to the selected RastPort. This
font should have alreay been opened with OpenFont() or
OpenDiskFont(). Any text you know output with Text() will appear
in the new font.
See: OpenFont(), CloseFont()
PAGE 546
----------------------------------------------------------------------------
SetRast(&RastPort, Colorregister)
This function sets all pixels in the selected RastPort bitmap, to
the color of the colour register from the ViewPort's colormap
for this RastPort.
When ColorRegister equals zero, then all the pixels of the ViewPort's
ColorMap are cleared to colour zero (= background color).
------------------------------------------------------------------
SetRGB4CM(&ColorMap, Colorregister, Red, Green, Blue)
This function works similar to SetRGB4. However, the color change
is not immediately visible. This happens only after you
calculate the Copper list again with RemakeDisplay.
The colour change first occurs in the selected colormap before it
is allowed to be visible.
Like LoadRGB4, the colormap is initialised with new values in the
background.
See: LoadRGB4()
------------------------------------------------------------------
SetRGB4(&ViewPort, ColorRegister, Reg, Green, Blue)
This function allows you to change the color of one color register
in the specified ViewPort. You pass the number of the color register
and the new red, green and blue components (0-15) for the new
color value.
SetRGB4() also changes the color entry in the ColorMap structure of
the ViewPort amd in the Copper list. This colour change is
immediately visible on the screen.
See: LoadRGB4(), GetRGB4()
PAGE 547
-----------------------------------------------------------------------------
NewStlye = SetSoftStyle(&RastPort, FontStyle, Style)
This function sets your desired, algorithmically generated font
style in the selected RastPort. You set the desired style in
FontStyle (see AskSoftStyle()) and use the value returned by
AskSoftStyle in Style. AskSoftStyle() provides the available
styles that can be used for the Style variable. For example,
it is possible that a font is already italic and after
AskSoftStyle() provided that information, it would be useless
to try to make that font italic.
SetSoftStyle() changes a font only when the style-bits are also
set in Style. After the change, NewStyle contains the font
generated by SetSoftStyle().
See: AskSoftStyle()
------------------------------------------------------------------
SortGList(&RastPort)
This routine sorts the GEL list of the selected RastPort. The
vsprite structures used for positioning vsprites and bobs are
sorted by their Y and X coordinates. The sort is performed by the
Y and then by the X coordinate.
After using SortGList() you use DrawGList() to display the GEL
list again.
See: DrawGList()
------------------------------------------------------------------
Text(&RastPort, &"string", NumCharacters)
This routine lets you display, at the graphic cursor position, any
desired text in the selected RastPort. You simply provide the
starting address of the output string and the number of characters
to be displayed.
See: TextLength()
------------------------------------------------------------------
Length = TextLength(&RastPort, &"String", NumCharacters)
This function has the same parameters as Text(). The length in
pixels for the text string is returned and the RastPorts currently
active font is used to display the text.
PAGE 548
See: Text(), SetFont()
-----------------------------------------------------------------------------
Position = VBeamPos()
This function returns the current vertical position of the
electronic raster beam in "position". The values that are returned
fall between 0 and 255 on PAL systems. Because the electron beam
actually scans 262 lines on PAL systems, the positions between
256 and 262 are returned as values between zero and 6.
After your program has received it, the value returned by
VBeamPos() is usually useless. Due to the Amiga's multitasking
capabilities, the millisecond reaction time, required by your
program to react, can be used up by another program or task.
------------------------------------------------------------------
WaitBlit()
This function pauses your program until the blitter has completed
its task. Be careful because a processor error can cause WaitBlit()
to return actually before completing the desired task. Your program
is then able to continue its tasks before they should occur.
Most often, this error occurs when you are using hires with
four bitplanes.
------------------------------------------------------------------
WaitBOVP(&ViewPort)
This function pauses your program until the electron beam reaches
the last row of the selected ViewPort (Bottom of ViewPort).
See: WaitTOF()
------------------------------------------------------------------
WiatTOF()
This function is similar to WaitTOF() except that the pause doesnt
happen until the end of the ViewPort. WaitTOF() waits for the
electronic beam to reach "Vertical Blank" (top of frame) or the
start of a new scan after completing any cyclic routines
(Interrupts)
See: WaitBOVF()
PAGE 549
-----------------------------------------------------------------------------
WritePixel(&RastPort,x,y)
This function sets a pixel at coordinates X and Y, in the APen
colour in the selected RastPort. Naturally, the current drawing
mode of the RastPort is used.
See: ReadPixel()
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
DISKFONTBASE
============
Now to the DiskFontBase functions (you must first open the library
"diskfont.libraries"
----------------------------------------------------------
Error = AvailFonts(&Buffer, BufferSize, Typ)
This function provides a complete list of the available system
fonts. This list is written into the memory area (&Buffer),
which contains the BuffserSize that you selected.
The first thing stored in the buffer is the AvailFontsHeader. This
contains the number of font entries that are stored (in
AvailFontsHeader.afh_NumEntries). Then the various AvailFonts
entries, which contain the type of font, (either in the system font
list (AFF_MEMORY) or on disk (AFF_DISK) and the more descriptiive
TextAttr structure are stored.
The TextAttr structure can be used to open a font. However, this
must be done by type (AFF_MEMORY / AFF_DISK) in order to open one
with OpenFont() or OpenDiskFont().
THe AvailFonts parameter TYP determines whether the Systemfontlist
(AFF_MEMORY), SYS:Fonts (AFF_DISK) or both are searched for
available fonts.
Please note that AvailFonts() does not verify the TextAttr structure
contents for SYS:Fonts from disk. When you open fonts using
OpenDiskFont() with the returned TextAttr structure of AvailFonts(),
you can encounter such undesired results as a system crash.
The results returned by AvailFonts() provide information on whether
or not enough memory is available to store all the AvailFont
structures. When error equals zero there is enough memory. However,
when error is not equal to zero or the number of additional bytes
that are required to contain all the AvailFonts structures is
returned instead.
PAGE 550
-----------------------------------------------------------------------------
*TextFont = OpenDiskFont(&TextAttr)
This function opens a font described by the TextAttr structure.
The SYS:Fonts directory is searched for a font that best matches
the TextAttr structure in style and size. If a matching font in the
TextAttr structure cannot be found, a value of zero is returned.
See: OpenFont.
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
INTUITIONBASE
=============
The following are the IntuitionBase routines (IntuitionBase is the
pointer to the Intuition library that you open with IntuitionBase =
(struct IntuitionBase *) OpenLibrary("intuition.library",0)
--------------------------------------------
CloseScreen(&Screen)
Use this function to close a screen that was opened earlier with
OpenScreen(). The memory used for the bitmap and all Intuition
screen structures (ViewPort, RastPort etc..) is released.
When you close the last user-opened screen, the workbench screen
is automatically active again. CloseScreen() does not check
whether all windows for a screen have been closed. If any
windows are still open a system crash will occur.
See: OpenScreen()
-----------------------------------------------------------------
CloseWindow(&Window)
This function closes a window you have opened with OpenWindow().
Make sure that you close all the windows in a screen before
attempting to close the screen window.
See: OpenScreen()
------------------------------------------------------------------
DisplayBeep(&Screen)
This function blinks the screen by quickly changing the background
color of the screen. This technique is used in order to make the
user aware of small errors.
PAGE 551
-----------------------------------------------------------------------------
By using a zero instead of a screen address you can blink all the
Intuition screens. However, this should only be used to indicate
a rather extreme user error.
------------------------------------------------------------------
MakeScreen(&Screen)
This function executes MakeVPort() for the ViewPort of the specified
screen. You can make changes to the intuition screens' ViewPorts
(such as color changes with LoadRGB4() and inform the copper
afterwards).
See: MakeVPort()
------------------------------------------------------------------
ModifyIDCMP(&Window,IDCMPFlags)
This function is used to change the IDCMP flags (Intuition Direct
Communication Message Ports) for a window. These flags are used
for various messages that are sent by Intuition to your window.
However, it is impossible to explain all the possibilities of the
IDCMP's in this Appendix.
------------------------------------------------------------------
OpenScreen(&NewScreen)
This function opens an Intuition screen that is further described
by the selected NewScreen structure. This function creates a
ViewPort and all the other required structures (bitmap, RastPort,
etc..). The new screen is linked to the Intuition View and
then displayed.
See: CloseScreen().
------------------------------------------------------------------
RemakeDisplay()
This funnction calculates a new Copper list for all intuition
screens. This means that for each screen, a MakeScreen() and
then a ReThinkDisplay() is called. When using this function,
you should disable multi-tasking for a short time.
See: MakeScreen(), ReThinkDisplay()
PAGE 552
-----------------------------------------------------------------------------
ReThinkDisplay()
This function executes MrgCop() and LoadView() for the intuition
View. Multitasking is turned off shortly while this is executing.
See: MakeScreen(), RemakeDisplay(), MrgCop(), LoadView()
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
Here are the DosBase routines (Please note that DosBase, just like the
ExecBase, dont have to be opened because in these C programs they are
always open).
Delay(Time)
This routine pauses you program "Time" * 1/60 seconds. Other
running tasks are not paused as with a pause using for().
------------------------------------------------------------------
Exit(ReturnValue)
This function allows you to exit a program loop at any time. When
you run your program as an 'overlay-process', the "return value"
is passed to your main process. We did not use the program overlay
technique in our examlple programs.
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
EXECBASE : The following are the execbase routines:
*Memory = AllocMem(NumBytes,Use)
This routine is used to declare NumBytes of memory for your use.
You must also specify what memory you require. When you use
MEMF_CHIP (MEMF = MEMoryFlag) the memory is allocated from the
lower 512K bytes area. This is especially important since this
memory must be used by all the Amiga processors (for example,
for bitplanes etc..)
With MEMF_PUBLIC you use a memory area from anywhere. This can
be an area above 512k bytes if you have more than 512K.
MEMF_CLEAR allows you to immediately clear the selected memory
area. You will receive the address of a completely cleared memory
area.
See: FreeMem()
PAGE 553
-----------------------------------------------------------------------------
CloseLibrary(&BasePointer)
Use this function to close a library you open earlier with
OpenLibrary(). Provide the address pointer that you received when
using OpenLibrary() in "BasePointer".
Please make sure you close all open libraries before exiting
your program.
See: OpenLibrary()
------------------------------------------------------------------
FreeMem(&Memory, Size)
You use this routine to release a memory area that was reserved.
Simply specify the starting address of the memory area and the
number of bytes reserved.
See: AllocMem()
------------------------------------------------------------------
Message = GetMsg(&Port)
By using this function you can intercept messages from Intuition.
This function waits until a message is sent.
See: AllocMem()
------------------------------------------------------------------
OpenLibrary(&LibName,Versionnumber)
Use this function to open the selected library which gives you
access to specific operating system routines.
For example, to use the graphic functions, open the graphic library
with GfxBase = (struct GfxBase *) OpenLibrary("graphics.
library",0). GfxBase is the pointer to the requested library
and must be used with CloseLibrary at the end of your program.
PAGE 554
-----------------------------------------------------------------------------
When you dont know the actual version number of the library, use
zero, which uses the current library version. However, when a
function is available only in a specific version of a library,
you should quickly exit your program is the library is not found.
------------------------------------------------------------------
ReplyMsg(&Port)
Use this function to tell intuition, for example, that you have
received and processed its messages.
PAGE 555
-----------------------------------------------------------------------------
APPENDIX C - THE HARDWARE REGISTERS
===================================
This appendix provdes an overview of the Amiga hardware registers. Those
registers are useful with Copper programming because they can be easily
changed through the copper.
Use the CMOVE() instruction with the register number that you want to
change. If you want to change a register by using the 68000, you should
only write to specific memory areas.
THe hardware registers are located in a memory area starting at $DFF000.
This means that you must use this address as an offset and then add the
value of the specific register address in order to use the 68000 to
access it.
To access the hardware registers with C, use the Custom structure that
you create with extern struct Custom custom. As with the Copper or
68000, you can access the individual registers by using custom.Name.
The following list describes hardware registers in detail. We have
provided the regsiter number as you would define them in your include
file hardware/custom.h. We also show the offset for each register from
$DFF000. So, both C and machine language programmers have the background
information on the registers and how to use them.
-----------------------------------------------------------------------------
adkcon $09E Audio and disk control (write)
adkconr $010 Audio and disk control (read)
As shown, you access these registers differently. You can either
write (adkcn) to one, or read (adkconr) from the other.
The bit structure of both registers is the same. However, even
though bit 15 is not affected by read operations, it is very
important for write operations.
Bit 15 SET/CLR:
When writing a word with this bit set, all bits (14-0) are written
into the register. Any unset bits in the word being written do
not change the corresponding bit already in the register.
PAGE 557
-----------------------------------------------------------------------------
If bit 15 is unset in the word being written, all set bits of the
written word clear any matching set bits in the register. Again,
any unset register bits are unaffected.
In order to clearly explain this, we have provided the following
short example: When writing the binary value %1111111111111110 all
bits in the register are set except for zero. With a value of
%0111111111111110 all bits in the register are cleared except bit
zero. This type of register control appears very often. Whenever a CLR/SET bit is used, the above rules will apply.
Bits 14,13 PRECOMP1/2:
These bits set the PreComp for disk operations. The value %00 in
both registers selects zero ns (nanoseconds). A value of %01
selects 140ns, %10 selects 280ns and %11 selects 560ns.
Bit 12 MFMPREC:
This bit selects the read format for a disk. If it is set, this
bit selects the normal mfm format. When it is unset, the GCR
format is selected as for Apple or Commodore 64 disks.
Bit 11 UARTBRK:
When this bit is set, all lines of the RS232 interface are set to
zero (Universal Asynchronous Receiver/Transmitter Break).
Bit 10 WORDSYNC:
Setting this bit starts the data transfer over the DMA channel
and each word read is synchronised with the word in DSKSYNC.
Bit 9 MSBSYNC:
This bit determines whether the high bit of a word is synchronised
in GCR format.
Bit 8 FAST
This bit allows you to set the timing for reading a bit from disk.
Setting this bit selects two microseconds, which is the required
timing for the MFM format. A value of zero for this bit sets the
timing to four microseconds, which is the correct timing for
GCR type formats. (Apple, Commodore 64).
Bits 7-4 ATPER3-0:
These bits allow you to modulate the sampling rate of the
inidividual audio channels. Setting ATPER3 stops the sound channel
output. By setting ATPER2, you can modulate the sampling rate of
audio channel three with audio channel two. Setting ATPER1
modulates the sampling rate of audio channel two with audio channel
one. ATPER0 sets the modulation sampling rate between audio
channels one and zero.
PAGE 558
-----------------------------------------------------------------------------
Bits 3-0 ATVOL3-0
These bits determine the volume modulation of the individual audio
channels. The pattern used is the same as ATPER3-0 except that the
volume is modulated.
------------------------------------------------------------------
aud[X].ac_ptr $0A0 Audio channel X start address.
The address for the data that will be sent over the sound DMA
channel (direct memory access = without the use of 68000) is
stored here.
This is actually a register pair where the data address' lower 15
bits are stored in $0A2 and the upper three bits are stored in
$0A0. Based on the custom declaration in the include file, the
*ac_ptr is already reserved by the compiler as a long word.
To directly access this register pair from the C language, you
must use an index value between 0 and 3 for the corresponding
audio channel (aud[X]).
Machine language programmers must always add X*12 words to access
a specific sound channel register. This register pair and the
following five registers represent a block divided into four
parts, one after the other. At the end of this Appendix we have
provided a table showing all the register addresses relative to
$DFF000.
Remember that here you can only use 18 bits for addressing. The
sound chip, as with the Blitter, only uses the lower 512k bytes
of memory.
------------------------------------------------------------------
aud[X].ac_len $0A4 Audio channel X length.
This register contains a count of the number of words to be sent
through the DMA channel for sound generation. You can set the
starting addres for these words in the register that is described
above.
------------------------------------------------------------------
aud[X].ac_per $0A6 Audio channel X sounding frequency.
In this register you specify how many bytes per second are used for
sound generation. Since the sound DMA channel is synchronised with
the screen DMA channel, only two bytes per raster row can be made
audible. Theoretically, it is possible to make two (bytes) *
262.5 (raster rows) * 59.94 (screen displayed) = 31468.5 bytes
per second audible in PAL systems.
Because the DMA controller is responsible for other tasks besides
sound generation, it is only possible to sample 28867 bytes per
second.
This means that you could send one byte through the sound channel
in 1/28867 seconds = 34.642 microseconds. This provides the value
for this register: ac_per = 34.642 microseconds/Num_Microseconds
for one scan.
PAGE 559
-----------------------------------------------------------------------------
The hardware determines the limits for the scan per timing cycle.
Since the timing cycle is 280 nanoseconds or 0.28 microseconds,
a value of 123 (34.643 microseconds / 280 nanoseconds) is the
smallest possible value for this register. If you select a smaller
value the DMA channel can no longer function properly.